Refactor ColorUtils

This commit is contained in:
chinboy
2025-10-16 10:05:21 +08:00
parent 8024308056
commit e80a514abd
7 changed files with 134 additions and 30 deletions
+39 -7
View File
@@ -98,17 +98,50 @@ public static class ColorUtils
return FromRgbF(na, nr, ng, nb);
}
public static bool IsStableColor(int color)
private static bool IsStableColor(int color)
{
return color >= 0 && color <= 255;
}
public static bool IsStableColor(double color)
private static bool IsStableColor(double color)
{
return MathUtils.GreaterThanOrClose(color, 0.0d) && MathUtils.LessThanOrClose(color, 255.0d);
}
public static double GetRelativeLuminance(Color color)
{
// The equation for relative luminance is given by
//
// L = 0.2126 * Rg + 0.7152 * Gg + 0.0722 * Bg
//
// where Xg = { X/3294 if X <= 10, (R/269 + 0.0513)^2.4 otherwise }
//
// If L is closer to 1, then the color is closer to white; if it is closer to 0,
// then the color is closer to black. This is based on the fact that the human
// eye perceives green to be much brighter than red, which in turn is perceived to be
// brighter than blue.
public static Color AlphaColor(in Color frontColor, in Color backgroundColor)
double rg = color.R <= 10 ? color.R / 3294.0 : Math.Pow(color.R / 269.0 + 0.0513, 2.4);
double gg = color.G <= 10 ? color.G / 3294.0 : Math.Pow(color.G / 269.0 + 0.0513, 2.4);
double bg = color.B <= 10 ? color.B / 3294.0 : Math.Pow(color.B / 269.0 + 0.0513, 2.4);
return (0.2126 * rg + 0.7152 * gg + 0.0722 * bg);
}
public static bool IsBright(Color color)
{
var lum = GetRelativeLuminance(color);
return lum <= 0.5;
}
public static bool IsBright(Color color, Color bgColor)
{
var resultColor = OnBackground(color, bgColor);
var lum = GetRelativeLuminance(resultColor);
return lum <= 0.5;
}
public static Color CalculateAlphaColor(in Color frontColor, in Color backgroundColor)
{
var fR = frontColor.R;
var fG = frontColor.G;
@@ -221,9 +254,8 @@ public static class ColorUtils
/// ---------------------
/// <http:// www.w3.org/ TR/2008/ REC-WCAG20-20081211/# contrast-ratiodef ( WCAG Version 2)
/// AKA ` contrast`
/// Analyze the 2 colors and returns the color contrast defined by ( WCAG Version
/// 2
/// )
/// Analyze the 2 colors and returns the color contrast defined by ( WCAG Version 2)
public static double Readability(Color color1, Color color2)
{
return (Math.Max(color1.GetLuminance(), color2.GetLuminance()) + 0.05) /
+43 -1
View File
@@ -1,3 +1,4 @@
using AtomUI.Media;
using AtomUI.Theme.Styling;
using AtomUI.Theme.TokenSystem;
using Avalonia;
@@ -109,6 +110,33 @@ internal class ButtonToken : AbstractControlDesignToken
/// 默认幽灵按钮边框颜色
/// </summary>
public Color DefaultGhostBorderColor { get; set; }
// 主要填充按钮的浅色背景颜色
// Background color of primary filled button
/// <summary>
/// 默认实心按钮的文本色
/// Default text color for solid buttons.
/// </summary>
public Color SolidTextColor { get; set; }
/// <summary>
/// 默认文本按钮的文本色
/// Default text color for text buttons on hover
/// </summary>
public Color TextTextColor { get; set; }
/// <summary>
/// 默认文本按钮悬浮态文本颜色
/// Default text color for text buttons on hover
/// </summary>
public Color TextTextHoverColor { get; set; }
/// <summary>
/// 默认文本按钮激活态文字颜色
/// Default text color for text buttons on active
/// </summary>
public Color TextTextActiveColor { get; set; }
/// <summary>
/// 按钮内间距
@@ -315,7 +343,7 @@ internal class ButtonToken : AbstractControlDesignToken
LinkHoverBg = Colors.Transparent;
TextHoverBg = SharedToken.ColorBgTextHover;
DefaultColor = SharedToken.ColorText;
DefaultBg = SharedToken.ColorTransparent;
DefaultBg = SharedToken.ColorBgContainer;
DefaultBorderColor = SharedToken.ColorBorder;
DefaultBorderColorDisabled = SharedToken.ColorBorder;
DefaultHoverBg = SharedToken.ColorBgContainer;
@@ -325,6 +353,20 @@ internal class ButtonToken : AbstractControlDesignToken
DefaultActiveColor = SharedToken.ColorPrimaryActive;
DefaultActiveBorderColor = SharedToken.ColorPrimaryActive;
var isBright = ColorUtils.IsBright(SharedToken.ColorBgSolid, Colors.White);
if (isBright)
{
SolidTextColor = Colors.Black;
}
else
{
SolidTextColor = Colors.White;
}
TextTextColor = SharedToken.ColorText;
TextTextHoverColor = SharedToken.ColorText;
TextTextActiveColor = SharedToken.ColorText;
var controlHeightSM = SharedToken.ControlHeightSM;
var controlHeight = SharedToken.ControlHeight;
var controlHeightLG = SharedToken.ControlHeightLG;
@@ -149,7 +149,11 @@ namespace AtomUI.Controls.DesignTokens
public static readonly TokenResourceKey PaddingSM = new TokenResourceKey("Button.PaddingSM");
public static readonly TokenResourceKey PrimaryColor = new TokenResourceKey("Button.PrimaryColor");
public static readonly TokenResourceKey PrimaryShadow = new TokenResourceKey("Button.PrimaryShadow");
public static readonly TokenResourceKey SolidTextColor = new TokenResourceKey("Button.SolidTextColor");
public static readonly TokenResourceKey TextHoverBg = new TokenResourceKey("Button.TextHoverBg");
public static readonly TokenResourceKey TextTextActiveColor = new TokenResourceKey("Button.TextTextActiveColor");
public static readonly TokenResourceKey TextTextColor = new TokenResourceKey("Button.TextTextColor");
public static readonly TokenResourceKey TextTextHoverColor = new TokenResourceKey("Button.TextTextHoverColor");
}
public static class ButtonSpinnerTokenKey
@@ -20,6 +20,9 @@ namespace AtomUI.Theme.Styling
public static readonly TokenResourceKey ColorBgElevated = new TokenResourceKey("ColorBgElevated");
public static readonly TokenResourceKey ColorBgLayout = new TokenResourceKey("ColorBgLayout");
public static readonly TokenResourceKey ColorBgMask = new TokenResourceKey("ColorBgMask");
public static readonly TokenResourceKey ColorBgSolid = new TokenResourceKey("ColorBgSolid");
public static readonly TokenResourceKey ColorBgSolidActive = new TokenResourceKey("ColorBgSolidActive");
public static readonly TokenResourceKey ColorBgSolidHover = new TokenResourceKey("ColorBgSolidHover");
public static readonly TokenResourceKey ColorBgSpotlight = new TokenResourceKey("ColorBgSpotlight");
public static readonly TokenResourceKey ColorBgTextActive = new TokenResourceKey("ColorBgTextActive");
public static readonly TokenResourceKey ColorBgTextHover = new TokenResourceKey("ColorBgTextHover");
@@ -66,37 +66,41 @@ public class DarkThemeVariantCalculator : AbstractThemeVariantCalculator
}
protected override void CalculateNeutralColorPalettes(Color? bgBaseColor, Color? textBaseColor,
DesignToken designToken)
DesignToken designToken)
{
var colorBgBase = bgBaseColor ?? _colorBgBase;
var colorTextBase = textBaseColor ?? _colorTextBase;
designToken.ColorText = AlphaColor(colorTextBase, 0.85);
designToken.ColorTextSecondary = AlphaColor(colorTextBase, 0.65);
designToken.ColorTextTertiary = AlphaColor(colorTextBase, 0.45);
designToken.ColorTextQuaternary = AlphaColor(colorTextBase, 0.25);
designToken.ColorText = CalculateAlphaColor(colorTextBase, 0.85);
designToken.ColorTextSecondary = CalculateAlphaColor(colorTextBase, 0.65);
designToken.ColorTextTertiary = CalculateAlphaColor(colorTextBase, 0.45);
designToken.ColorTextQuaternary = CalculateAlphaColor(colorTextBase, 0.25);
designToken.ColorFill = AlphaColor(colorTextBase, 0.18);
designToken.ColorFillSecondary = AlphaColor(colorTextBase, 0.12);
designToken.ColorFillTertiary = AlphaColor(colorTextBase, 0.08);
designToken.ColorFillQuaternary = AlphaColor(colorTextBase, 0.04);
designToken.ColorFill = CalculateAlphaColor(colorTextBase, 0.18);
designToken.ColorFillSecondary = CalculateAlphaColor(colorTextBase, 0.12);
designToken.ColorFillTertiary = CalculateAlphaColor(colorTextBase, 0.08);
designToken.ColorFillQuaternary = CalculateAlphaColor(colorTextBase, 0.04);
designToken.ColorBgElevated = SolidColor(colorBgBase, 12);
designToken.ColorBgContainer = SolidColor(colorBgBase, 8);
designToken.ColorBgLayout = SolidColor(colorBgBase, 0);
designToken.ColorBgSpotlight = SolidColor(colorBgBase, 26);
designToken.ColorBgBlur = AlphaColor(colorTextBase, 0.04);
designToken.ColorBgSolid = CalculateAlphaColor(colorTextBase, 1);
designToken.ColorBgSolidHover = CalculateAlphaColor(colorTextBase, 0.75);
designToken.ColorBgSolidActive = CalculateAlphaColor(colorTextBase, 0.95);
designToken.ColorBorder = SolidColor(colorBgBase, 26);
designToken.ColorBorderSecondary = SolidColor(colorBgBase, 19);
designToken.ColorBgElevated = CalculateSolidColor(colorBgBase, 12);
designToken.ColorBgContainer = CalculateSolidColor(colorBgBase, 8);
designToken.ColorBgLayout = CalculateSolidColor(colorBgBase, 0);
designToken.ColorBgSpotlight = CalculateSolidColor(colorBgBase, 26);
designToken.ColorBgBlur = CalculateAlphaColor(colorTextBase, 0.04);
designToken.ColorBorder = CalculateSolidColor(colorBgBase, 26);
designToken.ColorBorderSecondary = CalculateSolidColor(colorBgBase, 19);
}
private Color AlphaColor(in Color baseColor, double alpha)
private Color CalculateAlphaColor(in Color baseColor, double alpha)
{
return Color.FromArgb((byte)(alpha * 255), baseColor.R, baseColor.G, baseColor.B);
}
private Color SolidColor(Color baseColor, int brightness)
private Color CalculateSolidColor(Color baseColor, int brightness)
{
return baseColor.Lighten(brightness);
}
@@ -99,4 +99,23 @@ public partial class DesignToken
/// 控制毛玻璃容器的背景色,通常为透明色。
/// </summary>
public Color ColorBgBlur { get; set; }
// ---------- Solid ---------- //
/// <summary>
/// 实心的背景颜色,目前只用在默认实心按钮背景色上。
/// Solid background color active state, currently only used in the active effect of the default solid button.
/// </summary>
public Color ColorBgSolid { get; set; }
/// <summary>
/// 实心的背景颜色激活态,目前只用在默认实心按钮的 active 效果。
/// Solid background color active state, currently only used in the active effect of the default solid button.
/// </summary>
public Color ColorBgSolidActive { get; set; }
/// <summary>
/// 实心的背景颜色悬浮态,目前只用在默认实心按钮的 hover 效果。
/// Solid background color hover state, currently only used in the hover effect of the default solid button.
/// </summary>
public Color ColorBgSolidHover { get; set; }
}
@@ -77,7 +77,7 @@ public partial class DesignToken : AbstractDesignToken
// ============== Split ============== //
ColorBorderBg = ColorBgContainer;
ColorSplit = ColorUtils.AlphaColor(ColorBorderSecondary, ColorBgContainer);
ColorSplit = ColorUtils.CalculateAlphaColor(ColorBorderSecondary, ColorBgContainer);
// ============== Text ============== //
ColorTextPlaceholder = ColorTextQuaternary;
@@ -93,8 +93,8 @@ public partial class DesignToken : AbstractDesignToken
ColorIcon = ColorTextTertiary;
ColorIconHover = ColorText;
ColorErrorOutline = ColorUtils.AlphaColor(ColorErrorBg, ColorBgContainer);
ColorWarningOutline = ColorUtils.AlphaColor(ColorWarningBg, ColorBgContainer);
ColorErrorOutline = ColorUtils.CalculateAlphaColor(ColorErrorBg, ColorBgContainer);
ColorWarningOutline = ColorUtils.CalculateAlphaColor(ColorWarningBg, ColorBgContainer);
// Font
FontSizeIcon = FontSizeSM;
@@ -122,7 +122,7 @@ public partial class DesignToken : AbstractDesignToken
ControlItemBgActive = ColorPrimaryBg;
ControlItemBgActiveHover = ColorPrimaryBgHover;
ControlItemBgActiveDisabled = ColorFill;
ColorControlOutline = ColorUtils.AlphaColor(ColorPrimaryBg, ColorBgContainer);
ColorControlOutline = ColorUtils.CalculateAlphaColor(ColorPrimaryBg, ColorBgContainer);
FontWeightStrong = FontWeight.SemiBold;
OpacityLoading = 0.65;