介绍
本示例实现了一个网格渐变的画笔调色板,能够根据给定的 HSL 类型颜色和色阶数,按亮度生成渐变色,用户可以通过调色板选择颜色并在画布上绘制路径。
效果图预览
使用说明
- 页面底部展示当前画笔颜色和预设的常用颜色,点击预设的常用颜色可以修改画笔颜色。
- 点击画笔颜色,显示网格渐变的调色板,选择调色板上的颜色可以修改画笔颜色。
- 在图片上触摸并拖动手指,可以绘制路径,路径颜色为当前选中的画笔颜色。
实现思路
-
调色板(HslPalette)渐变方案和布局。
- 根据给定的
hslHues
(HSL颜色列表)和levels
(色阶数量)生成按亮度渐变的颜色,并根据给定的的渐变亮度起止点(gradientStartPoint
和gradientEndPoint
),使不同颜色的同一色阶亮度相同。源码参考PaletteMainPage.ets
private hslHues: HslType[] = []; // HSL 类型颜色的源数组 private levels: number = 0; // 渐变色阶数 private gradientStartPoint: number = 0; // 渐变开始点的亮度值 private gradientEndPoint: number = 0; // 渐变结束点的亮度值 // TODO:知识点:根据 HSL 色相数组和色阶数生成按亮度渐变的 HEX 格式颜色 computeHSLGradient(hues: HslType[], levels: number): string[] { if (levels <= 0) { return []; } const colors: string[] = []; for (let i = 0; i < levels; i++) { hues.forEach(hsl => { // 根据给定的渐变亮度起止点和所处色阶计算渐变亮度 const fadedL = this.gradientStartPoint + Math.round(i * (this.gradientEndPoint - this.gradientStartPoint) / levels); // 逐渐变淡 // 将 HSL 转换为 HEX 格式 const hex = hslToHex(hsl.hue, hsl.saturation, fadedL); // 添加到颜色数组 colors.push(hex); }); } return colors; }
- 由于ArkUI组件不能直接使用HSL类型的颜色,所以获取到渐变亮度后需要通过
hslToHex
函数将 HSL 颜色转换为 HEX 颜色再存储在colors
数组中。源码参考ColorTypeConverter.ets
/** * 将 HSL 颜色模型转换为 HEX 颜色模型 * * @param {number} hue - 色相 (Hue),范围为 0 到 360 * @param {number} saturation - 饱和度 (Saturation),范围为 0 到 100 * @param {number} lightness - 亮度 (Lightness),范围为 0 到 100 * @returns {string} - 返回 HEX 颜色值,格式为 '#RRGGBB' */ export function hslToHex(hue: number, saturation: number, lightness: number): string { // 将 HSL 转换为 RGB const rgb: RgbType = hslToRgb(hue, saturation, lightness); // 返回 HEX 颜色值 return rgbToHex(rgb.red, rgb.green, rgb.blue); } /** * 将 HSL 颜色值转换为 RGB 颜色格式。 * * @param {number} hue - 色相,范围为 0-360。 * @param {number} saturation - 饱和度,范围为 0-100,表示颜色的强度。 * @param {number} lightness - 亮度,范围为 0-100,表示颜色的明暗程度。 * @returns {rgbType} - 返回一个包含 RGB 值的对象,格式为 { red, green, blue },每个值的范围为 0-255。 */ function hslToRgb(hue: number, saturation: number, lightness: number): RgbType { let red: number, green: number, blue: number; // 将饱和度和亮度从百分比转换为小数 saturation /= 100; lightness /= 100; if (saturation === 0) { // 无饱和度,返回灰色 red = Math.round(lightness * 255); // 灰色的 Red 值 green = Math.round(lightness * 255); // 灰色的 Green 值 blue = Math.round(lightness * 255); // 灰色的 Blue 值 } else { // 辅助函数:根据 HSL 值计算 RGB 值,处理不同的色相区间 const convertHueToRgb = (baseValue: number, brightnessMultiplier: number, hueFraction: number): number => { // 确保 hueFraction 在 0 到 1 之间 if (hueFraction < 0) { hueFraction += 1; } if (hueFraction > 1) { hueFraction -= 1; } // 第一个区间 if (hueFraction < 1 / 6) { return baseValue + (brightnessMultiplier - baseValue) * 6 * hueFraction; } // 第二个区间 if (hueFraction < 1 / 2) { return brightnessMultiplier; } // 第三个区间 if (hueFraction < 2 / 3) { return baseValue + (brightnessMultiplier - baseValue) * (2 / 3 - hueFraction) * 6; } // 第四个区间 return baseValue; }; // 根据亮度计算中间值 brightnessMultiplier 和 baseValue const brightnessMultiplier = lightness < 0.5 ? lightness * (1 + satur
- 根据给定的