namespace AntDesignWPF { using System; using System.Windows.Media; /// /// 提供颜色调色板相关的工具方法,用于生成颜色的色阶变化。 /// 主要用于 Ant Design 主题色系的生成和调整。 /// public static class ColorPalette { #region Fields /// 色相调整步长 private const int hueStep = 2; /// 饱和度主要调整步长 private const int saturationStep = 16; /// 饱和度次要调整步长 private const int saturationStep2 = 5; /// 亮度调整步长(用于浅色) private const int brightnessStep1 = 5; /// 亮度调整步长(用于深色) private const int brightnessStep2 = 15; /// 浅色色阶数量 private const int lightColorCount = 5; /// 深色色阶数量 private const int darkColorCount = 4; #endregion #region Public Methods /// /// 根据基准色和索引生成对应的色阶颜色 /// /// 基准色 /// 色阶索引(1-10),1-6为浅色系,7-10为深色系 /// 生成的色阶颜色 public static Color Toning(Color color, int index) { bool isLight = index <= 6; HSV hsv = Color2Hsv(color); int i = isLight ? lightColorCount + 1 - index : index - lightColorCount - 1; return Hsv2Color(GetHue(hsv, i, isLight), GetSaturation(hsv, i, isLight), GetValue(hsv, i, isLight), color.A); } #endregion #region Private Methods /// /// 计算色相值 /// /// HSV颜色值 /// 调整步数 /// 是否为浅色系 /// 调整后的色相值 private static double GetHue(HSV hsv, int i, bool isLight) { double hue; // 根据色相范围决定增减方向 if (hsv.H >= 60 && hsv.H <= 240) { hue = isLight ? hsv.H - hueStep * i : hsv.H + hueStep * i; } else { hue = isLight ? hsv.H + hueStep * i : hsv.H - hueStep * i; } // 确保色相值在0-360范围内 if (hue < 0) { hue += 360; } else if (hue >= 360) { hue -= 360; } return Math.Round(hue); } /// /// 计算饱和度值 /// /// HSV颜色值 /// 调整步数 /// 是否为浅色系 /// 调整后的饱和度值(0-100) private static double GetSaturation(HSV hsv, int i, bool isLight) { double saturation; if (isLight) { saturation = Math.Round(hsv.S * 100) - saturationStep * i; } else if (i == darkColorCount) { saturation = Math.Round(hsv.S * 100) + saturationStep; } else { saturation = Math.Round(hsv.S * 100) + saturationStep2 * i; } // 确保饱和度在合理范围内 if (saturation > 100) { saturation = 100; } if (isLight && i == lightColorCount && saturation > 10) { saturation = 10; } if (saturation < 6) { saturation = 6; } return Math.Round(saturation); } /// /// 计算明度值 /// /// HSV颜色值 /// 调整步数 /// 是否为浅色系 /// 调整后的明度值(0-100) private static double GetValue(HSV hsv, int i, bool isLight) { if (isLight) { return Math.Round(hsv.V * 100) + brightnessStep1 * i; } return Math.Round(hsv.V * 100) - brightnessStep2 * i; } /// /// 将HSV颜色值转换为RGB颜色 /// /// 色相(0-360) /// 饱和度(0-100) /// 明度(0-100) /// 透明度 /// RGB颜色 private static Color Hsv2Color(double h, double s, double v, byte a) { h = Bound(h, 360) * 6; s = Bound(s, 100); v = Bound(v, 100); double i = Math.Floor(h); double f = h - i; double p = v * (1 - s), q = v * (1 - f * s), t = v * (1 - (1 - f) * s); int mod = (int)(i % 6); double r = new double[6] { v, q, p, p, t, v }[mod], g = new double[6] { t, v, v, q, p, p }[mod], b = new double[6] { p, p, t, v, v, q }[mod]; r = Math.Min(255, Math.Max(0, r * 255)); g = Math.Min(255, Math.Max(0, g * 255)); b = Math.Min(255, Math.Max(0, b * 255)); return new Color() { R = (byte)Math.Round(r), G = (byte)Math.Round(g), B = (byte)Math.Round(b), A = a }; } /// /// 将RGB颜色转换为HSV颜色值 /// /// RGB颜色 /// HSV颜色值 private static HSV Color2Hsv(Color color) { double r = Bound(color.R, 255), g = Bound(color.G, 255), b = Bound(color.B, 255); double max = Math.Max(r, Math.Max(g, b)), min = Math.Min(r, Math.Min(g, b)); double h = 0, v = max, d = max - min; double s = max == 0 ? 0 : d / max; if (max != min) { if (max == r) { h = (g - b) / d + (g < b ? 6 : 0); } else if (max == g) { h = (b - r) / d + 2; } else if (max == b) { h = (r - g) / d + 4; } h /= 6; } return new HSV() { H = h * 360, S = s, V = v }; } /// /// 将输入值从[0, n]范围转换到[0, 1]范围 /// /// 输入值 /// 最大值 /// 归一化后的值 private static double Bound(double n, double max) { n = Math.Min(max, Math.Max(0, n)); // 处理浮点数舍入误差 if ((Math.Abs(n - max) < 0.000001)) { return 1; } // 转换到[0, 1]范围 return (n % max) / max; } #endregion } /// /// HSV颜色值结构 /// H: 色相 (0-360) /// S: 饱和度 (0-1) /// V: 明度 (0-1) /// internal struct HSV { public double H; public double S; public double V; } }