You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Blazor可复用组件:如何将背景色字符串转为HSL格式

Blazor组件中实现字符串背景色转HSL并自动计算文本配色

方法一:C#后端解析颜色(兼容所有Blazor宿主)

由于System.Drawing在Blazor WebAssembly环境中无法使用,我们可以手动实现颜色解析逻辑,将常见格式的颜色字符串(十六进制、RGB/RGBA)转换为HSL格式。

首先定义HSL数据结构:

public struct HslColor
{
    public double Hue { get; set; } // 取值范围0-360
    public double Saturation { get; set; } // 取值范围0-100(百分比)
    public double Lightness { get; set; } // 取值范围0-100(百分比)
    public double Alpha { get; set; } // 取值范围0-1
}

实现颜色解析工具类:

public static class ColorParser
{
    public static HslColor ParseToHsl(string colorString)
    {
        // 处理空值或无效输入, fallback到默认色
        if (string.IsNullOrWhiteSpace(colorString))
            return ParseHexToHsl("#DEF4F58C");

        // 处理十六进制格式(#RRGGBB 或 #RRGGBBAA)
        if (colorString.StartsWith("#"))
            return ParseHexToHsl(colorString);

        // 处理RGB/RGBA格式
        if (colorString.StartsWith("rgb(") || colorString.StartsWith("rgba("))
            return ParseRgbToHsl(colorString);

        // 格式不支持时返回默认值
        return ParseHexToHsl("#DEF4F58C");
    }

    private static HslColor ParseHexToHsl(string hex)
    {
        // 处理缩写格式(如#RGB、#RGBA)
        hex = hex.TrimStart('#');
        if (hex.Length == 3)
            hex = $"{hex[0]}{hex[0]}{hex[1]}{hex[1]}{hex[2]}{hex[2]}FF";
        else if (hex.Length == 4)
            hex = $"{hex[0]}{hex[0]}{hex[1]}{hex[1]}{hex[2]}{hex[2]}{hex[3]}{hex[3]}";
        else if (hex.Length == 6)
            hex += "FF";

        // 解析RGBA值为0-1的小数
        var r = Convert.ToInt32(hex.Substring(0, 2), 16) / 255.0;
        var g = Convert.ToInt32(hex.Substring(2, 2), 16) / 255.0;
        var b = Convert.ToInt32(hex.Substring(4, 2), 16) / 255.0;
        var a = Convert.ToInt32(hex.Substring(6, 2), 16) / 255.0;

        return RgbToHsl(r, g, b, a);
    }

    private static HslColor ParseRgbToHsl(string rgb)
    {
        // 提取RGB/RGBA中的数字部分
        var parts = rgb.Replace("rgb(", "")
                       .Replace("rgba(", "")
                       .Replace(")", "")
                       .Split(',')
                       .Select(p => double.TryParse(p.Trim(), out var val) ? val : 0)
                       .ToArray();

        var r = parts[0] / 255.0;
        var g = parts[1] / 255.0;
        var b = parts[2] / 255.0;
        var a = parts.Length >=4 ? parts[3] : 1;

        return RgbToHsl(r, g, b, a);
    }

    private static HslColor RgbToHsl(double r, double g, double b, double a)
    {
        double max = Math.Max(r, Math.Max(g, b));
        double min = Math.Min(r, Math.Min(g, b));
        double h, s, l = (max + min) / 2;

        if (max == min)
        {
            h = s = 0; // 灰度色
        }
        else
        {
            double d = max - min;
            s = l > 0.5 ? d / (2 - max - min) : d / (max + min);

            if (max == r)
                h = (g - b) / d + (g < b ? 6 : 0);
            else if (max == g)
                h = (b - r) / d + 2;
            else
                h = (r - g) / d + 4;

            h *= 60;
        }

        return new HslColor
        {
            Hue = Math.Round(h),
            Saturation = Math.Round(s * 100),
            Lightness = Math.Round(l * 100),
            Alpha = a
        };
    }
}

在Blazor组件中使用:

@code {
    /// <summary>
    /// Define the colour of the card. It can accept any string value. The default is #DEF4F58C Hexadecimal.
    /// </summary>
    [Parameter] public string BackgroundColour { get; set; } = "#DEF4F58C";

    private HslColor _bgHsl;

    protected override void OnInitialized()
    {
        _bgHsl = ColorParser.ParseToHsl(BackgroundColour);
    }

    // 根据背景亮度自动计算文本颜色
    private string TextColour => _bgHsl.Lightness > 50 ? "#000000" : "#FFFFFF";
}

将HSL值通过CSS变量传递给组件样式:

<div style="background-color: @BackgroundColour; color: @TextColour; --bg-h: @_bgHsl.Hue; --bg-s: @_bgHsl.Saturation%; --bg-l: @_bgHsl.Lightness%">
    <!-- 组件内容 -->
</div>

方法二:前端JS互操作(利用浏览器的颜色解析能力)

如果不想手动处理复杂颜色格式(比如命名色red、原生HSL格式),可以借助浏览器的getComputedStyle API自动解析。

添加JS方法(放在wwwroot/js/interop.js):

window.getColorAsHsl = async (elementId) => {
    const element = document.getElementById(elementId);
    if (!element) return null;
    
    const computedStyle = getComputedStyle(element);
    const bgColor = computedStyle.backgroundColor;
    
    // 利用浏览器将任意颜色转换为HSL格式
    const tempDiv = document.createElement('div');
    tempDiv.style.color = bgColor;
    document.body.appendChild(tempDiv);
    const hslColor = getComputedStyle(tempDiv).color;
    document.body.removeChild(tempDiv);
    
    // 提取HSL数值
    const matches = hslColor.match(/hsl\((\d+),\s*(\d+)%,\s*(\d+)%\)/);
    if (!matches) return null;
    
    return {
        hue: parseInt(matches[1]),
        saturation: parseInt(matches[2]),
        lightness: parseInt(matches[3]),
        alpha: bgColor.includes('rgba') ? parseFloat(bgColor.split(',')[3].replace(')', '')) : 1
    };
};

在Blazor组件中调用:

@inject IJSRuntime JSRuntime

<!-- 用于解析颜色的隐藏元素 -->
<div id="bg-color-target" style="display: none; background-color: @BackgroundColour"></div>

<div style="background-color: @BackgroundColour; color: @TextColour; --bg-h: @_bgHsl.Hue; --bg-s: @_bgHsl.Saturation%; --bg-l: @_bgHsl.Lightness%">
    <!-- 组件内容 -->
</div>

@code {
    [Parameter] public string BackgroundColour { get; set; } = "#DEF4F58C";
    private HslColor _bgHsl;
    private string TextColour => _bgHsl.Lightness > 50 ? "#000000" : "#FFFFFF";

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            var hslData = await JSRuntime.InvokeAsync<HslColor>("getColorAsHsl", "bg-color-target");
            if (hslData != null)
            {
                _bgHsl = hslData;
                StateHasChanged();
            }
        }
    }

    public struct HslColor
    {
        public int Hue { get; set; }
        public int Saturation { get; set; }
        public int Lightness { get; set; }
        public double Alpha { get; set; }
    }
}

使用CSS calc实现动态配色

得到HSL变量后,可通过CSS calc实现更灵活的配色逻辑:

.card-content {
    /* 文本颜色随背景亮度反向调整 */
    color: hsl(var(--bg-h), var(--bg-s), calc(var(--bg-l) > 50 ? 10% : 90%));
    /* 边框颜色比背景深/浅10% */
    border-color: hsl(var(--bg-h), var(--bg-s), calc(var(--bg-l) - 10%));
}

内容的提问来源于stack exchange,提问作者Ben Pugh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 01:52:41