在这里插入图片描述

目录

  1. 概述
  2. 工具功能
  3. 核心实现
  4. Kotlin 源代码
  5. JavaScript 编译代码
  6. ArkTS 调用代码
  7. 实战案例
  8. 最佳实践

概述

本文档介绍如何在 Kotlin Multiplatform (KMP) 鸿蒙跨端开发中实现一个完整的网页设计配色方案生成工具。网页设计中的颜色选择是创建视觉吸引力和用户体验的关键因素。这个案例展示了如何使用 Kotlin 的色彩科学和配色理论来创建一个功能丰富的配色方案生成工具。

配色方案生成工具能够根据用户选择的主色调,自动生成多种配色方案,包括互补色、类似色、三角配色和分裂互补色等。这些配色方案基于色彩理论的原理,确保生成的颜色组合在视觉上和谐且专业。通过 KMP,这个工具可以无缝编译到 JavaScript,在 OpenHarmony 应用中运行,为设计师提供专业的配色方案生成服务。

工具的特点

  • 多种配色方案:支持互补色、类似色、三角配色、分裂互补色等多种方案
  • 色彩空间转换:支持 HEX、RGB、HSL 等多种色彩空间
  • 颜色名称识别:自动识别主色调的颜色名称
  • 色彩变体生成:生成浅色和深色变体
  • 设计建议:提供专业的设计建议和应用场景
  • 跨端兼容:一份 Kotlin 代码可同时服务多个平台

工具功能

1. 主色调输入和验证

工具支持 HEX 格式的颜色输入(例如 FF6B35 表示橙色):

  • 颜色格式:6 位十六进制格式
  • 格式验证:确保输入的颜色格式正确
  • 颜色信息:显示 HEX、RGB、HSL 三种格式的颜色信息

2. 互补色配色

互补色是色轮上相对的两种颜色,具有最高的对比度:

  • 原理:互补色相差 180°
  • 特点:对比度最高,视觉冲击力强
  • 应用:用于强调和突出重要元素

3. 类似色配色

类似色是色轮上相邻的颜色,具有和谐统一的特点:

  • 原理:类似色相差 ±30°
  • 特点:和谐统一,视觉舒适
  • 应用:用于创建统一的视觉风格

4. 三角配色

三角配色使用三个均匀分布在色轮上的颜色:

  • 原理:三个颜色相差 120°
  • 特点:活力十足,视觉平衡
  • 应用:用于复杂的设计和多元素布局

5. 分裂互补色

分裂互补色使用一种颜色和其互补色两侧的颜色:

  • 原理:颜色相差 ±150°
  • 特点:平衡的对比,不过于刺眼
  • 应用:用于需要对比但又不过于激进的设计

6. 色彩变体

工具生成浅色和深色变体,用于不同的应用场景:

  • 浅色变体:亮度 80%,用于背景色
  • 深色变体:亮度 30%,用于文本色
  • 应用:创建完整的色彩系统

7. 颜色名称识别

工具根据色调自动识别颜色名称:

  • 12 种基本颜色:红、橙、黄、黄绿、绿、青绿、青、蓝、紫蓝、紫、洋红、红紫
  • 应用:帮助设计师快速理解颜色特性

8. 设计建议和应用场景

工具提供专业的设计建议和应用场景:

  • 设计建议:如何使用各种配色方案
  • 应用场景:网站品牌色、按钮色、背景色、文本色、强调色等

核心实现

算法原理

网页设计配色方案生成工具的核心算法包括:

  1. 颜色格式转换:HEX → RGB → HSL
  2. 色调计算:根据 RGB 计算 HSL 中的色调(H)
  3. 配色方案生成:基于色调生成各种配色方案
  4. 颜色格式转换:HSL → RGB → HEX
  5. 颜色名称识别:根据色调识别颜色名称

RGB 到 HSL 的转换

HSL(色调、饱和度、亮度)是一个更直观的色彩空间,便于生成配色方案。

转换步骤:

  1. 将 RGB 值归一化到 0-1 范围
  2. 计算最大值(max)和最小值(min)
  3. 计算亮度(L):(max + min) / 2
  4. 计算饱和度(S):根据亮度计算
  5. 计算色调(H):根据最大值是 R、G 还是 B 计算

配色方案生成

基于 HSL 的色调(H)生成各种配色方案:

  • 互补色:H + 180°
  • 类似色:H ± 30°
  • 三角配色:H + 120°、H + 240°
  • 分裂互补色:H ± 150°

HSL 到 RGB 的转换

将生成的 HSL 颜色转换回 RGB 格式,然后转换为 HEX。


Kotlin 源代码

// 案例 38: 网页设计中的颜色选择 - 配色方案生成工具
@OptIn(ExperimentalJsExport::class)
@JsExport
fun webDesignColorSchemeGenerator(inputData: String = "FF6B35"): String {
    if (inputData.isEmpty()) {
        return "❌ 错误: 输入不能为空\n请输入: 主色调 (HEX 格式, 如: FF6B35)"
    }
    
    val hexColor = inputData.trim().uppercase()
    
    // 验证十六进制格式
    if (!hexColor.matches(Regex("^[0-9A-F]{6}$"))) {
        return "❌ 错误: 颜色格式不正确\n请使用6位十六进制格式 (例如: FF6B35)"
    }
    
    // 1. 转换HEX到RGB
    val r = hexColor.substring(0, 2).toInt(16)
    val g = hexColor.substring(2, 4).toInt(16)
    val b = hexColor.substring(4, 6).toInt(16)
    
    // 2. 转换RGB到HSL
    val rNorm = r / 255.0
    val gNorm = g / 255.0
    val bNorm = b / 255.0
    
    val max = maxOf(rNorm, gNorm, bNorm)
    val min = minOf(rNorm, gNorm, bNorm)
    val l = (max + min) / 2.0
    
    val h = when {
        max == min -> 0.0
        max == rNorm -> (60 * (((gNorm - bNorm) / (max - min)) % 6) + 360) % 360
        max == gNorm -> (60 * (((bNorm - rNorm) / (max - min)) + 2)) % 360
        else -> (60 * (((rNorm - gNorm) / (max - min)) + 4)) % 360
    }
    
    val s = when {
        max == min -> 0.0
        l < 0.5 -> (max - min) / (max + min)
        else -> (max - min) / (2.0 - max - min)
    }
    
    // 3. 生成互补色
    val complementaryH = (h + 180) % 360
    val complementaryRgb = hslToRgb(complementaryH, s, l)
    val complementaryHex = rgbToHex(complementaryRgb.first, complementaryRgb.second, complementaryRgb.third)
    
    // 4. 生成类似色(±30度)
    val analogousH1 = (h + 30) % 360
    val analogousH2 = (h - 30 + 360) % 360
    val analogousRgb1 = hslToRgb(analogousH1, s, l)
    val analogousRgb2 = hslToRgb(analogousH2, s, l)
    val analogousHex1 = rgbToHex(analogousRgb1.first, analogousRgb1.second, analogousRgb1.third)
    val analogousHex2 = rgbToHex(analogousRgb2.first, analogousRgb2.second, analogousRgb2.third)
    
    // 5. 生成三角配色(120度间隔)
    val triadic1H = (h + 120) % 360
    val triadic2H = (h + 240) % 360
    val triadicRgb1 = hslToRgb(triadic1H, s, l)
    val triadicRgb2 = hslToRgb(triadic2H, s, l)
    val triadicHex1 = rgbToHex(triadicRgb1.first, triadicRgb1.second, triadicRgb1.third)
    val triadicHex2 = rgbToHex(triadicRgb2.first, triadicRgb2.second, triadicRgb2.third)
    
    // 6. 生成分裂互补色(±150度)
    val splitComplementary1H = (h + 150) % 360
    val splitComplementary2H = (h - 150 + 360) % 360
    val splitComplementaryRgb1 = hslToRgb(splitComplementary1H, s, l)
    val splitComplementaryRgb2 = hslToRgb(splitComplementary2H, s, l)
    val splitComplementaryHex1 = rgbToHex(splitComplementaryRgb1.first, splitComplementaryRgb1.second, splitComplementaryRgb1.third)
    val splitComplementaryHex2 = rgbToHex(splitComplementaryRgb2.first, splitComplementaryRgb2.second, splitComplementaryRgb2.third)
    
    // 7. 生成浅色和深色变体
    val lightRgb = hslToRgb(h, s, 0.8)
    val lightHex = rgbToHex(lightRgb.first, lightRgb.second, lightRgb.third)
    
    val darkRgb = hslToRgb(h, s, 0.3)
    val darkHex = rgbToHex(darkRgb.first, darkRgb.second, darkRgb.third)
    
    // 8. 获取颜色名称
    val colorName = getColorName(h)
    
    // 9. 获取设计建议
    val designTips = mutableListOf<String>()
    designTips.add("• 主色用于品牌标识和重点元素")
    designTips.add("• 互补色用于强调和对比")
    designTips.add("• 类似色用于和谐的过渡")
    designTips.add("• 三角配色适合复杂的设计")
    designTips.add("• 浅色用于背景,深色用于文本")
    designTips.add("• 确保颜色对比度满足无障碍要求")
    
    return "🎨 网页设计配色方案生成器\n" +
           "━━━━━━━━━━━━━━━━━━━━━\n" +
           "🌈 主色调信息\n" +
           "HEX: #$hexColor\n" +
           "RGB: ($r, $g, $b)\n" +
           "HSL: (${(h * 100).toInt() / 100.0}°, ${(s * 100).toInt()}%, ${(l * 100).toInt()}%)\n" +
           "颜色: $colorName\n\n" +
           "🎯 互补色配色\n" +
           "互补色: #$complementaryHex\n" +
           "说明: 对比度最高,用于强调\n\n" +
           "🔄 类似色配色\n" +
           "类似色1: #$analogousHex1\n" +
           "类似色2: #$analogousHex2\n" +
           "说明: 和谐统一,视觉舒适\n\n" +
           "△ 三角配色\n" +
           "颜色1: #$triadicHex1\n" +
           "颜色2: #$triadicHex2\n" +
           "说明: 三个颜色均匀分布,活力十足\n\n" +
           "◇ 分裂互补色\n" +
           "颜色1: #$splitComplementaryHex1\n" +
           "颜色2: #$splitComplementaryHex2\n" +
           "说明: 平衡的对比,不过于刺眼\n\n" +
           "💫 色彩变体\n" +
           "浅色: #$lightHex (背景色)\n" +
           "深色: #$darkHex (文本色)\n\n" +
           "💡 设计建议\n" +
           designTips.joinToString("\n") + "\n\n" +
           "📋 应用场景\n" +
           "• 网站品牌色: #$hexColor\n" +
           "• 按钮色: #$complementaryHex\n" +
           "• 背景色: #$lightHex\n" +
           "• 文本色: #$darkHex\n" +
           "• 强调色: #$triadicHex1\n\n" +
           "━━━━━━━━━━━━━━━━━━━━━\n" +
           "✅ 配色方案生成完成!"
}

// 辅助函数: 获取颜色名称
fun getColorName(hue: Double): String {
    return when {
        hue < 15 || hue >= 345 -> "红色"
        hue < 45 -> "橙色"
        hue < 75 -> "黄色"
        hue < 105 -> "黄绿色"
        hue < 135 -> "绿色"
        hue < 165 -> "青绿色"
        hue < 195 -> "青色"
        hue < 225 -> "蓝色"
        hue < 255 -> "紫蓝色"
        hue < 285 -> "紫色"
        hue < 315 -> "洋红色"
        else -> "红紫色"
    }
}

// 辅助函数: HSL转RGB
fun hslToRgb(h: Double, s: Double, l: Double): Triple<Int, Int, Int> {
    val c = (1 - kotlin.math.abs(2 * l - 1)) * s
    val hPrime = h / 60.0
    val x = c * (1 - kotlin.math.abs(hPrime % 2 - 1))
    
    val (r1, g1, b1) = when {
        hPrime < 1 -> Triple(c, x, 0.0)
        hPrime < 2 -> Triple(x, c, 0.0)
        hPrime < 3 -> Triple(0.0, c, x)
        hPrime < 4 -> Triple(0.0, x, c)
        hPrime < 5 -> Triple(x, 0.0, c)
        else -> Triple(c, 0.0, x)
    }
    
    val m = l - c / 2
    val r = ((r1 + m) * 255).toInt()
    val g = ((g1 + m) * 255).toInt()
    val b = ((b1 + m) * 255).toInt()
    
    return Triple(r, g, b)
}

// 辅助函数: RGB转HEX
fun rgbToHex(r: Int, g: Int, b: Int): String {
    val rHex = r.toString(16).padStart(2, '0').uppercase()
    val gHex = g.toString(16).padStart(2, '0').uppercase()
    val bHex = b.toString(16).padStart(2, '0').uppercase()
    return rHex + gHex + bHex
}

Kotlin 代码详解

这个 Kotlin 函数实现了一个完整的网页设计配色方案生成工具。函数接收一个 HEX 格式的颜色作为主色调。

首先,函数进行输入验证,确保颜色格式正确。

接下来,函数将 HEX 颜色转换为 RGB,然后转换为 HSL。HSL 色彩空间更便于生成配色方案,因为色调(H)直接对应色轮上的位置。

然后,函数基于主色调的色调值生成各种配色方案:

  • 互补色:H + 180°
  • 类似色:H ± 30°
  • 三角配色:H + 120°、H + 240°
  • 分裂互补色:H ± 150°

最后,函数将所有生成的 HSL 颜色转换回 RGB 和 HEX 格式,并返回一个格式化的结果字符串。


JavaScript 编译代码

// 编译后的 JavaScript 代码(部分示例)
function webDesignColorSchemeGenerator(inputData) {
    if (inputData === undefined) {
        inputData = "FF6B35";
    }
    
    if (inputData.length === 0) {
        return "❌ 错误: 输入不能为空\n请输入: 主色调 (HEX 格式, 如: FF6B35)";
    }
    
    var hexColor = inputData.trim().toUpperCase();
    
    // 验证十六进制格式
    var hexRegex = /^[0-9A-F]{6}$/;
    if (!hexRegex.test(hexColor)) {
        return "❌ 错误: 颜色格式不正确\n请使用6位十六进制格式 (例如: FF6B35)";
    }
    
    // 转换HEX到RGB
    var r = parseInt(hexColor.substring(0, 2), 16);
    var g = parseInt(hexColor.substring(2, 4), 16);
    var b = parseInt(hexColor.substring(4, 6), 16);
    
    // 转换RGB到HSL
    var rNorm = r / 255.0;
    var gNorm = g / 255.0;
    var bNorm = b / 255.0;
    
    var max = Math.max(rNorm, gNorm, bNorm);
    var min = Math.min(rNorm, gNorm, bNorm);
    var l = (max + min) / 2.0;
    
    var h;
    if (max === min) {
        h = 0;
    } else if (max === rNorm) {
        h = (60 * (((gNorm - bNorm) / (max - min)) % 6) + 360) % 360;
    } else if (max === gNorm) {
        h = (60 * (((bNorm - rNorm) / (max - min)) + 2)) % 360;
    } else {
        h = (60 * (((rNorm - gNorm) / (max - min)) + 4)) % 360;
    }
    
    var s;
    if (max === min) {
        s = 0;
    } else if (l < 0.5) {
        s = (max - min) / (max + min);
    } else {
        s = (max - min) / (2.0 - max - min);
    }
    
    // 生成互补色
    var complementaryH = (h + 180) % 360;
    var complementaryRgb = hslToRgb(complementaryH, s, l);
    var complementaryHex = rgbToHex(complementaryRgb[0], complementaryRgb[1], complementaryRgb[2]);
    
    // 生成类似色
    var analogousH1 = (h + 30) % 360;
    var analogousH2 = (h - 30 + 360) % 360;
    var analogousRgb1 = hslToRgb(analogousH1, s, l);
    var analogousRgb2 = hslToRgb(analogousH2, s, l);
    var analogousHex1 = rgbToHex(analogousRgb1[0], analogousRgb1[1], analogousRgb1[2]);
    var analogousHex2 = rgbToHex(analogousRgb2[0], analogousRgb2[1], analogousRgb2[2]);
    
    // 生成三角配色
    var triadic1H = (h + 120) % 360;
    var triadic2H = (h + 240) % 360;
    var triadicRgb1 = hslToRgb(triadic1H, s, l);
    var triadicRgb2 = hslToRgb(triadic2H, s, l);
    var triadicHex1 = rgbToHex(triadicRgb1[0], triadicRgb1[1], triadicRgb1[2]);
    var triadicHex2 = rgbToHex(triadicRgb2[0], triadicRgb2[1], triadicRgb2[2]);
    
    // 生成分裂互补色
    var splitComplementary1H = (h + 150) % 360;
    var splitComplementary2H = (h - 150 + 360) % 360;
    var splitComplementaryRgb1 = hslToRgb(splitComplementary1H, s, l);
    var splitComplementaryRgb2 = hslToRgb(splitComplementary2H, s, l);
    var splitComplementaryHex1 = rgbToHex(splitComplementaryRgb1[0], splitComplementaryRgb1[1], splitComplementaryRgb1[2]);
    var splitComplementaryHex2 = rgbToHex(splitComplementaryRgb2[0], splitComplementaryRgb2[1], splitComplementaryRgb2[2]);
    
    // 生成浅色和深色变体
    var lightRgb = hslToRgb(h, s, 0.8);
    var lightHex = rgbToHex(lightRgb[0], lightRgb[1], lightRgb[2]);
    
    var darkRgb = hslToRgb(h, s, 0.3);
    var darkHex = rgbToHex(darkRgb[0], darkRgb[1], darkRgb[2]);
    
    // 获取颜色名称
    var colorName = getColorName(h);
    
    var designTips = [
        "• 主色用于品牌标识和重点元素",
        "• 互补色用于强调和对比",
        "• 类似色用于和谐的过渡",
        "• 三角配色适合复杂的设计",
        "• 浅色用于背景,深色用于文本",
        "• 确保颜色对比度满足无障碍要求"
    ];
    
    return "🎨 网页设计配色方案生成器\n" +
           "━━━━━━━━━━━━━━━━━━━━━\n" +
           "🌈 主色调信息\n" +
           "HEX: #" + hexColor + "\n" +
           "RGB: (" + r + ", " + g + ", " + b + ")\n" +
           "HSL: (" + (Math.floor(h * 100) / 100) + "°, " + Math.floor(s * 100) + "%, " + Math.floor(l * 100) + "%)\n" +
           "颜色: " + colorName + "\n\n" +
           "🎯 互补色配色\n" +
           "互补色: #" + complementaryHex + "\n" +
           "说明: 对比度最高,用于强调\n\n" +
           "🔄 类似色配色\n" +
           "类似色1: #" + analogousHex1 + "\n" +
           "类似色2: #" + analogousHex2 + "\n" +
           "说明: 和谐统一,视觉舒适\n\n" +
           "△ 三角配色\n" +
           "颜色1: #" + triadicHex1 + "\n" +
           "颜色2: #" + triadicHex2 + "\n" +
           "说明: 三个颜色均匀分布,活力十足\n\n" +
           "◇ 分裂互补色\n" +
           "颜色1: #" + splitComplementaryHex1 + "\n" +
           "颜色2: #" + splitComplementaryHex2 + "\n" +
           "说明: 平衡的对比,不过于刺眼\n\n" +
           "💫 色彩变体\n" +
           "浅色: #" + lightHex + " (背景色)\n" +
           "深色: #" + darkHex + " (文本色)\n\n" +
           "💡 设计建议\n" +
           designTips.join("\n") + "\n\n" +
           "📋 应用场景\n" +
           "• 网站品牌色: #" + hexColor + "\n" +
           "• 按钮色: #" + complementaryHex + "\n" +
           "• 背景色: #" + lightHex + "\n" +
           "• 文本色: #" + darkHex + "\n" +
           "• 强调色: #" + triadicHex1 + "\n\n" +
           "━━━━━━━━━━━━━━━━━━━━━\n" +
           "✅ 配色方案生成完成!";
}

function getColorName(hue) {
    if (hue < 15 || hue >= 345) return "红色";
    if (hue < 45) return "橙色";
    if (hue < 75) return "黄色";
    if (hue < 105) return "黄绿色";
    if (hue < 135) return "绿色";
    if (hue < 165) return "青绿色";
    if (hue < 195) return "青色";
    if (hue < 225) return "蓝色";
    if (hue < 255) return "紫蓝色";
    if (hue < 285) return "紫色";
    if (hue < 315) return "洋红色";
    return "红紫色";
}

function hslToRgb(h, s, l) {
    var c = (1 - Math.abs(2 * l - 1)) * s;
    var hPrime = h / 60.0;
    var x = c * (1 - Math.abs(hPrime % 2 - 1));
    
    var r1, g1, b1;
    if (hPrime < 1) {
        r1 = c; g1 = x; b1 = 0;
    } else if (hPrime < 2) {
        r1 = x; g1 = c; b1 = 0;
    } else if (hPrime < 3) {
        r1 = 0; g1 = c; b1 = x;
    } else if (hPrime < 4) {
        r1 = 0; g1 = x; b1 = c;
    } else if (hPrime < 5) {
        r1 = x; g1 = 0; b1 = c;
    } else {
        r1 = c; g1 = 0; b1 = x;
    }
    
    var m = l - c / 2;
    var r = Math.floor((r1 + m) * 255);
    var g = Math.floor((g1 + m) * 255);
    var b = Math.floor((b1 + m) * 255);
    
    return [r, g, b];
}

function rgbToHex(r, g, b) {
    var rHex = r.toString(16).padStart(2, '0').toUpperCase();
    var gHex = g.toString(16).padStart(2, '0').toUpperCase();
    var bHex = b.toString(16).padStart(2, '0').toUpperCase();
    return rHex + gHex + bHex;
}

JavaScript 代码详解

Kotlin 代码编译到 JavaScript 后,保留了原有的逻辑结构,但使用 JavaScript 的语法和 API。主要的转换包括:

  1. 数学函数:Kotlin 的 maxOf()minOf() 转换为 JavaScript 的 Math.max()Math.min()
  2. 条件语句:Kotlin 的 when 表达式转换为 JavaScript 的 if-else
  3. 字符串操作:Kotlin 的 padStart() 转换为 JavaScript 的 padStart()
  4. 数组操作:Kotlin 的 Triple 转换为 JavaScript 的数组

ArkTS 调用代码

import { webDesignColorSchemeGenerator } from './hellokjs';

@Entry
@Component
struct Index {
  @State message: string = '准备就绪';
  @State mainColor: string = 'FF6B35';
  @State resultText: string = '';
  @State isLoading: boolean = false;

  aboutToAppear(): void {
    this.generateNewCase();
  }

  generateNewCase(): void {
    this.resultText = '';
    this.message = '准备就绪';
    
    const samples = [
      'FF6B35',
      '0066CC',
      '00CC99',
      'FF3366',
      'FFCC00',
      '9933FF',
      '33CC99',
      'FF9900'
    ];
    
    const random = samples[Math.floor(Math.random() * samples.length)];
    this.mainColor = random;
  }

  generate(): void {
    this.isLoading = true;
    try {
      const result: string = webDesignColorSchemeGenerator(this.mainColor);
      this.resultText = result;
      console.log(result);
      this.message = '✓ 配色方案生成完成';
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : String(error);
      this.message = `✗ 错误: ${errorMessage}`;
    } finally {
      this.isLoading = false;
    }
  }

  build() {
    Column() {
      // ===== 顶部标题栏 - 设计蓝色主题 =====
      Column() {
        Text('🎨 Web Design Color Scheme')
          .fontSize(28)
          .fontWeight(FontWeight.Bold)
          .fontColor(Color.White)
          .margin({ bottom: 8 })
        
        Text('Professional Color Palette Generator')
          .fontSize(13)
          .fontColor('#B3E5FC')
      }
      .width('100%')
      .padding(24)
      .backgroundColor('#0277BD')
      .alignItems(HorizontalAlign.Start)

      // ===== 主内容区域 =====
      Scroll() {
        Column() {
          // 输入卡片
          Column() {
            Row() {
              Text('🎨 Main Color')
                .fontSize(16)
                .fontWeight(FontWeight.Bold)
                .fontColor('#FFFFFF')
              
              Blank()
              
              Text('🎲 Random')
                .fontSize(12)
                .fontColor(Color.White)
                .padding({ left: 10, right: 10, top: 6, bottom: 6 })
                .backgroundColor('#004D7A')
                .borderRadius(12)
                .onClick(() => {
                  this.generateNewCase();
                })
            }
            .width('100%')
            .margin({ bottom: 18 })

            // 颜色输入
            TextInput({ placeholder: 'Main Color (HEX)', text: this.mainColor })
              .width('100%')
              .height(50)
              .padding(14)
              .fontSize(15)
              .fontColor('#000000')
              .placeholderColor('#999999')
              .border({ width: 2, color: '#0277BD' })
              .borderRadius(12)
              .backgroundColor('#E1F5FE')
              .onChange((value: string) => {
                this.mainColor = value;
              })
              .margin({ bottom: 20 })

            // 生成按钮
            Button(this.isLoading ? 'Generating...' : 'Generate Palette')
              .width('100%')
              .height(54)
              .fontSize(16)
              .fontWeight(FontWeight.Bold)
              .fontColor(Color.White)
              .backgroundColor(this.isLoading ? '#004D7A' : '#0277BD')
              .borderRadius(14)
              .onClick(() => {
                if (!this.isLoading) {
                  this.generate();
                }
              })
          }
          .width('90%')
          .padding(20)
          .backgroundColor('#FFFFFF')
          .borderRadius(16)
          .margin({ top: 20, bottom: 20, left: 'auto', right: 'auto' })
          .border({ width: 2, color: '#0277BD' })

          // 状态提示卡片
          if (this.message !== '准备就绪') {
            Row() {
              Text(this.message.startsWith('✓') ? '✅' : '⚠️')
                .fontSize(20)
                .margin({ right: 12 })

              Text(this.message)
                .fontSize(14)
                .fontColor(this.message.startsWith('✓') ? '#4ECDC4' : '#FF6B6B')
                .fontWeight(FontWeight.Bold)
                .layoutWeight(1)
            }
            .width('90%')
            .padding(16)
            .backgroundColor(this.message.startsWith('✓') ? '#1a3a3a' : '#3a1a1a')
            .border({ width: 2, color: this.message.startsWith('✓') ? '#4ECDC4' : '#FF6B6B' })
            .borderRadius(14)
            .margin({ bottom: 20, left: 'auto', right: 'auto' })
            .alignItems(VerticalAlign.Center)
          }

          // 结果卡片
          if (this.resultText) {
            Column() {
              Row() {
                Text('📊 Color Scheme')
                  .fontSize(14)
                  .fontWeight(FontWeight.Bold)
                  .fontColor('#0277BD')
              }
              .width('100%')
              .padding(14)
              .backgroundColor('#E1F5FE')
              .borderRadius(12)
              .margin({ bottom: 14 })
              .border({ width: 1, color: '#0277BD' })

              Text(this.resultText)
                .fontSize(12)
                .fontFamily('monospace')
                .fontColor('#004D7A')
                .width('100%')
                .padding(14)
                .backgroundColor('#E1F5FE')
                .borderRadius(12)
                .border({ width: 1, color: '#0288D1' })
            }
            .width('90%')
            .padding(16)
            .backgroundColor('#E1F5FE')
            .borderRadius(16)
            .margin({ bottom: 20, left: 'auto', right: 'auto' })
            .border({ width: 2, color: '#0277BD' })
          }

          // 底部提示
          Column() {
            Row() {
              Text('💡')
                .fontSize(18)
                .margin({ right: 10 })
              
              Text('🎨 Design Tips')
                .fontSize(14)
                .fontWeight(FontWeight.Bold)
                .fontColor('#0277BD')
            }
            .width('100%')
            .margin({ bottom: 12 })

            Text('• Enter a main color in HEX format\n• Generate multiple color schemes\n• Get professional design advice\n• Create harmonious palettes')
              .fontSize(12)
              .fontColor('#004D7A')
              .lineHeight(1.6)
          }
          .width('90%')
          .padding(16)
          .backgroundColor('#E1F5FE')
          .borderRadius(16)
          .margin({ bottom: 20, left: 'auto', right: 'auto' })
          .border({ width: 2, color: '#0277BD' })

          Blank()
            .height(20)
        }
        .width('100%')
      }
      .layoutWeight(1)
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#E1F5FE')
  }
}

ArkTS 代码详解

这个 ArkTS 组件实现了网页设计配色方案生成工具的用户界面。组件使用了 OpenHarmony 的 ArkTS 语言,提供了一个现代化的、设计蓝色主题的用户界面。

组件定义了一个 @State 属性来存储主色调。这个属性与输入框绑定,当用户输入数据时,这个属性会自动更新。

generateNewCase() 方法生成随机的颜色样本,帮助用户快速测试应用。用户可以点击"Random"按钮来生成随机数据。

generate() 方法调用 Kotlin 编译的 JavaScript 函数 webDesignColorSchemeGenerator(),并将主色调作为参数传递。函数返回的配色方案会显示在结果卡片中。

用户界面包括一个输入框(主色调)、一个生成按钮、一个状态提示卡片、一个结果卡片和一个提示卡片。所有元素都使用了设计蓝色主题。


实战案例

案例 1:橙色配色方案

输入:FF6B35

系统生成的配色方案:

  • 主色调:#FF6B35(橙色)
  • 互补色:#35B8FF(蓝色)
  • 类似色1:#FFAA35、类似色2:#FF3535
  • 三角配色:#35FF6B、#6B35FF
  • 分裂互补色:#35FFFF、#FF35AA
  • 浅色变体:#FFCC99(背景色)
  • 深色变体:#663300(文本色)

案例 2:蓝色配色方案

输入:0066CC

系统生成的配色方案:

  • 主色调:#0066CC(蓝色)
  • 互补色:#CCAA00(金色)
  • 类似色1:#0099CC、类似色2:#0033CC
  • 三角配色:#00CC66、#CC0066
  • 分裂互补色:#00CCAA、#CC0033
  • 浅色变体:#99CCFF(背景色)
  • 深色变体:#003366(文本色)

案例 3:绿色配色方案

输入:00CC99

系统生成的配色方案:

  • 主色调:#00CC99(绿色)
  • 互补色:#CC0066(洋红色)
  • 类似色1:#00CCCC、类似色2:#00CC66
  • 三角配色:#CC0099、#99CC00
  • 分裂互补色:#CC0033、#CC3300
  • 浅色变体:#99FFEE(背景色)
  • 深色变体:#003333(文本色)

最佳实践

1. 选择合适的配色方案

不同的配色方案适用于不同的设计场景:

  • 互补色:用于需要高对比度和强调的设计
  • 类似色:用于需要和谐统一的设计
  • 三角配色:用于复杂的设计和多元素布局
  • 分裂互补色:用于需要对比但又不过于激进的设计

2. 考虑无障碍性

确保颜色组合满足无障碍要求:

  • 对比度:确保文本和背景有足够的对比度
  • 色盲友好:不要仅依赖颜色来传达信息
  • 测试:在不同的显示设备上测试颜色

3. 建立色彩系统

创建一个完整的色彩系统:

  • 主色:品牌标识和重点元素
  • 辅助色:强调和对比
  • 背景色:浅色变体
  • 文本色:深色变体

4. 保持一致性

在整个设计中保持颜色的一致性:

  • 品牌一致性:使用相同的主色调
  • 视觉层次:使用不同的颜色表示不同的优先级
  • 文化考虑:考虑不同文化对颜色的理解

5. 测试和迭代

不断测试和改进配色方案:

  • 用户反馈:收集用户对颜色的反馈
  • A/B 测试:测试不同的配色方案
  • 性能监控:监控不同配色方案的用户参与度

总结

网页设计中的颜色选择 - 配色方案生成工具展示了如何使用 Kotlin Multiplatform 技术创建一个功能丰富、跨端兼容的配色方案生成应用。通过采用色彩理论的原理,系统能够帮助设计师快速生成专业的配色方案。

这个案例不仅展示了 KMP 的强大功能,还演示了如何将色彩科学和设计理论知识转化为实用的应用功能。无论是网页设计、移动应用还是品牌设计,设计师都可以使用这个工具来快速生成和谐的配色方案,提高设计效率和质量。

通过使用这个配色方案生成工具,设计师可以确保他们的设计在视觉上和谐、专业且易于访问,为用户创造更好的视觉体验。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐