在 JavaScript 中解析 CSS 颜色最有效的方法是什么?

问题描述 投票:0回答:13

给定一个有效的 CSS 颜色值字符串:

  • #fff
  • #ffffff
  • 白色
  • RGB(255, 255, 255)

我需要获取以下格式的数字数组:[R,G,B]

在 JavaScript 中执行此操作最有效的方法是什么(假设是主流浏览器)?

javascript css performance parsing colors
13个回答
36
投票
function parseColor(input) {
    var m;

显然,数值比名称更容易解析。所以我们先做这些。

    m = input.match(/^#([0-9a-f]{3})$/i)[1];
    if( m) {
        // in three-character format, each value is multiplied by 0x11 to give an
        // even scale from 0x00 to 0xff
        return [
            parseInt(m.charAt(0),16)*0x11,
            parseInt(m.charAt(1),16)*0x11,
            parseInt(m.charAt(2),16)*0x11
        ];
    }

就是一个。现在是完整的六位数字格式:

    m = input.match(/^#([0-9a-f]{6})$/i)[1];
    if( m) {
        return [
            parseInt(m.substr(0,2),16),
            parseInt(m.substr(2,2),16),
            parseInt(m.substr(4,2),16)
        ];
    }

现在

rgb()
格式:

    m = input.match(/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i);
    if( m) {
        return [m[1],m[2],m[3]];
    }

您还可以选择添加对

rgba
格式的支持,如果添加 HSL2RGB 转换功能,甚至还可以添加对
hsl
/
hsla
的支持。

最后是指定的颜色。

    return ({
        "red":[255,0,0],
        "yellow":[255,255,0],
        // ... and so on. Yes, you have to define ALL the colour codes.
    })[input];

并关闭该功能:

}

事实上,我不知道为什么我要费心写这些。我刚刚注意到您指定了“假设主要浏览器”,我假设这也意味着“最新”?如果是这样的话...

function parseColor(input) {
    var div = document.createElement('div'), m;
    div.style.color = input;
    m = getComputedStyle(div).color.match(/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i);
    if( m) return [m[1],m[2],m[3]];
    else throw new Error("Colour "+input+" could not be parsed.");
}

最新的浏览器会将任何给定的颜色以其计算样式转换为

rgb()
格式。把它拿回来,然后读出来。


26
投票

对于 HTML5 兼容浏览器,我使用指定值将单个像素写入

<canvas>
,然后读回
rgba
四边形。

为了性能,我记住了这个函数,这样重复调用相同的颜色字符串就不必执行画布操作。

编辑针对 ES6 进行了更新并删除了 jQuery 依赖项

编辑(1j01)添加了无效颜色检测,以及支持传递后备颜色的功能

let memoize = function(factory, ctx) {
    var cache = {};
    return function(key) {
        if (!(key in cache)) {
            cache[key] = factory.call(ctx, key);
        }
        return cache[key];
    };
};

let colorToRGBA = (function() {
    var canvas = document.createElement('canvas');
    canvas.width = canvas.height = 1;
    var ctx = canvas.getContext('2d');

    return memoize(function(col) {
        ctx.clearRect(0, 0, 1, 1);
        // In order to detect invalid values,
        // we can't rely on col being in the same format as what fillStyle is computed as,
        // but we can ask it to implicitly compute a normalized value twice and compare.
        ctx.fillStyle = '#000';
        ctx.fillStyle = col;
        var computed = ctx.fillStyle;
        ctx.fillStyle = '#fff';
        ctx.fillStyle = col;
        if (computed !== ctx.fillStyle) {
            return; // invalid color
        }
        ctx.fillRect(0, 0, 1, 1);
        return [ ... ctx.getImageData(0, 0, 1, 1).data ];
    });
})();

colorToRGBA('white') // [255, 255, 255, 255]
colorToRGBA('blah') // undefined

let colorOrFallbackColorToRGBA = (color, fallbackColor)=> {
    // Don't short-circuit getting the fallback RGBA -
    // it's already memoized, and we want to show an error
    // if the fallback color is invalid even if the main color is valid
    var fallbackRGBA = colorToRGBA(fallbackColor);
    if (!fallbackRGBA) {
        throw new Error(`Invalid fallbackColor ${
            fallbackColor != null ? JSON.stringify(fallbackColor) : fallbackColor
        }`);
    }
    return colorToRGBA(color) || fallbackRGBA;
};

colorOrFallbackColorToRGBA('white', 'transparent') // [255, 255, 255, 255]
colorOrFallbackColorToRGBA('blah', 'transparent') // [0, 0, 0, 0]

24
投票

更快更有效的方式

除了@NiettheDarkAbsol 的正确答案之外,还有一些方面:

  • backgroundColor 可以是

    rgb( 3 values )
    rgba( 4 values)

  • match
    函数很好,但是使用正则表达式很昂贵!只要有可能,请选择
    split

此功能更简单快捷:

function parseColor(input) {
    return input.split("(")[1].split(")")[0].split(",");
}

好的返回值仍然是字符串,并且它们包含不需要的空格,但如果在数学表达式中使用,它们将正常工作!

无论如何,我更喜欢这个:它们可能会按原样包含:

var bgColors = document.getElementById('myDiv').
                 backgroundColor.split("(")[1].split(")")[0].split(",");

支持
#RnGnBn
表格(IEx),如Emile Bergeron的评论

所建议

有一个小而快速的功能可与

rgb(r,g,b)
rgba(r,g,b,a)
#RGB
#RRGGBB
#RRRGGGBBB
配合使用:

function parseColor(input) {
    if (input.substr(0,1)=="#") {
    var collen=(input.length-1)/3;
    var fact=[17,1,0.062272][collen-1];
    return [
        Math.round(parseInt(input.substr(1,collen),16)*fact),
        Math.round(parseInt(input.substr(1+collen,collen),16)*fact),
        Math.round(parseInt(input.substr(1+2*collen,collen),16)*fact)
    ];
    }
    else return input.split("(")[1].split(")")[0].split(",").map(x=>+x);
}

演示

function parseColor(input) {
    if (input.substr(0,1)=="#") {
    var collen=(input.length-1)/3;
    var fact=[17,1,0.062272][collen-1];
    return [
        Math.round(parseInt(input.substr(1,collen),16)*fact),
        Math.round(parseInt(input.substr(1+collen,collen),16)*fact),
        Math.round(parseInt(input.substr(1+2*collen,collen),16)*fact)
    ];
    }
    else return input.split("(")[1].split(")")[0].split(",").map(x=>+x);
}

[ "rgb(123,45,67)", "rgb( 123, 45 , 67 )", "rgba(123,45,67,0.5)", "#F70",
  "#FF7700", "#FFF777000", "#FF8000", "#FFF800000", "#F80" ].forEach(
    function(color){
        colors=parseColor(color);
        if (colors.length<4) colors.push('1.0');
        document.getElementById('out').innerHTML+=
          '<tr><td style="background:'+color+';" />'+
          '<td>'+ colors.join('</td><td>')+'</td>'+
          '<td>parseColor("'+color+'");</td></tr>';
    }
);
th { width: 3em; }
<table id="out" style="font-family: mono;background:SlateGrey">
<tr><th></th><th>Red</th><th>Green</th><th>Blue</th><th>Alpha</th><th>Code</th></tr>
</table>


7
投票

死灵术。
对于任何真正需要它的人,这里有完全工作且功能完整的代码。
将其视为对“黑暗阿卜索尔尼特”答案的补充
干杯。

function parseColor(input) {
    var mm;
    var m;
    // Obviously, the numeric values will be easier to parse than names.So we do those first.
    mm = input.match(/^#?([0-9a-f]{3})$/i);
    if (mm) {
        m = mm[1];
        // in three-character format, each value is multiplied by 0x11 to give an
        // even scale from 0x00 to 0xff
        return [
            parseInt(m.charAt(0), 16) * 0x11,
            parseInt(m.charAt(1), 16) * 0x11,
            parseInt(m.charAt(2), 16) * 0x11
        ];
    }
    // That's one. Now for the full six-digit format: 
    mm = input.match(/^#?([0-9a-f]{6})$/i);
    if (mm) {
        m = mm[1];
        return [
            parseInt(m.substr(0, 2), 16),
            parseInt(m.substr(2, 2), 16),
            parseInt(m.substr(4, 2), 16)
        ];
    }
    // And now for rgb() format:
    var mm = input.match(/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i);
    if (mm) {
        return [mm[1], mm[2], mm[3]];
    }
    // https://www.w3schools.com/colors/colors_names.asp
    // https://en.wikipedia.org/wiki/Web_colors
    // http://www.colors.commutercreative.com/grid/
    var webColors = {
        "AliceBlue": "#F0F8FF",
        "AntiqueWhite": "#FAEBD7",
        "Aqua": "#00FFFF",
        "Aquamarine": "#7FFFD4",
        "Azure": "#F0FFFF",
        "Beige": "#F5F5DC",
        "Bisque": "#FFE4C4",
        "Black": "#000000",
        "BlanchedAlmond": "#FFEBCD",
        "Blue": "#0000FF",
        "BlueViolet": "#8A2BE2",
        "Brown": "#A52A2A",
        "BurlyWood": "#DEB887",
        "CadetBlue": "#5F9EA0",
        "Chartreuse": "#7FFF00",
        "Chocolate": "#D2691E",
        "Coral": "#FF7F50",
        "CornflowerBlue": "#6495ED",
        "Cornsilk": "#FFF8DC",
        "Crimson": "#DC143C",
        "Cyan": "#00FFFF",
        "DarkBlue": "#00008B",
        "DarkCyan": "#008B8B",
        "DarkGoldenRod": "#B8860B",
        "DarkGray": "#A9A9A9",
        "DarkGrey": "#A9A9A9",
        "DarkGreen": "#006400",
        "DarkKhaki": "#BDB76B",
        "DarkMagenta": "#8B008B",
        "DarkOliveGreen": "#556B2F",
        "DarkOrange": "#FF8C00",
        "DarkOrchid": "#9932CC",
        "DarkRed": "#8B0000",
        "DarkSalmon": "#E9967A",
        "DarkSeaGreen": "#8FBC8F",
        "DarkSlateBlue": "#483D8B",
        "DarkSlateGray": "#2F4F4F",
        "DarkSlateGrey": "#2F4F4F",
        "DarkTurquoise": "#00CED1",
        "DarkViolet": "#9400D3",
        "DeepPink": "#FF1493",
        "DeepSkyBlue": "#00BFFF",
        "DimGray": "#696969",
        "DimGrey": "#696969",
        "DodgerBlue": "#1E90FF",
        "FireBrick": "#B22222",
        "FloralWhite": "#FFFAF0",
        "ForestGreen": "#228B22",
        "Fuchsia": "#FF00FF",
        "Gainsboro": "#DCDCDC",
        "GhostWhite": "#F8F8FF",
        "Gold": "#FFD700",
        "GoldenRod": "#DAA520",
        "Gray": "#808080",
        "Grey": "#808080",
        "Green": "#008000",
        "GreenYellow": "#ADFF2F",
        "HoneyDew": "#F0FFF0",
        "HotPink": "#FF69B4",
        "IndianRed ": "#CD5C5C",
        "Indigo ": "#4B0082",
        "Ivory": "#FFFFF0",
        "Khaki": "#F0E68C",
        "Lavender": "#E6E6FA",
        "LavenderBlush": "#FFF0F5",
        "LawnGreen": "#7CFC00",
        "LemonChiffon": "#FFFACD",
        "LightBlue": "#ADD8E6",
        "LightCoral": "#F08080",
        "LightCyan": "#E0FFFF",
        "LightGoldenRodYellow": "#FAFAD2",
        "LightGray": "#D3D3D3",
        "LightGrey": "#D3D3D3",
        "LightGreen": "#90EE90",
        "LightPink": "#FFB6C1",
        "LightSalmon": "#FFA07A",
        "LightSeaGreen": "#20B2AA",
        "LightSkyBlue": "#87CEFA",
        "LightSlateGray": "#778899",
        "LightSlateGrey": "#778899",
        "LightSteelBlue": "#B0C4DE",
        "LightYellow": "#FFFFE0",
        "Lime": "#00FF00",
        "LimeGreen": "#32CD32",
        "Linen": "#FAF0E6",
        "Magenta": "#FF00FF",
        "Maroon": "#800000",
        "MediumAquaMarine": "#66CDAA",
        "MediumBlue": "#0000CD",
        "MediumOrchid": "#BA55D3",
        "MediumPurple": "#9370DB",
        "MediumSeaGreen": "#3CB371",
        "MediumSlateBlue": "#7B68EE",
        "MediumSpringGreen": "#00FA9A",
        "MediumTurquoise": "#48D1CC",
        "MediumVioletRed": "#C71585",
        "MidnightBlue": "#191970",
        "MintCream": "#F5FFFA",
        "MistyRose": "#FFE4E1",
        "Moccasin": "#FFE4B5",
        "NavajoWhite": "#FFDEAD",
        "Navy": "#000080",
        "OldLace": "#FDF5E6",
        "Olive": "#808000",
        "OliveDrab": "#6B8E23",
        "Orange": "#FFA500",
        "OrangeRed": "#FF4500",
        "Orchid": "#DA70D6",
        "PaleGoldenRod": "#EEE8AA",
        "PaleGreen": "#98FB98",
        "PaleTurquoise": "#AFEEEE",
        "PaleVioletRed": "#DB7093",
        "PapayaWhip": "#FFEFD5",
        "PeachPuff": "#FFDAB9",
        "Peru": "#CD853F",
        "Pink": "#FFC0CB",
        "Plum": "#DDA0DD",
        "PowderBlue": "#B0E0E6",
        "Purple": "#800080",
        "RebeccaPurple": "#663399",
        "Red": "#FF0000",
        "RosyBrown": "#BC8F8F",
        "RoyalBlue": "#4169E1",
        "SaddleBrown": "#8B4513",
        "Salmon": "#FA8072",
        "SandyBrown": "#F4A460",
        "SeaGreen": "#2E8B57",
        "SeaShell": "#FFF5EE",
        "Sienna": "#A0522D",
        "Silver": "#C0C0C0",
        "SkyBlue": "#87CEEB",
        "SlateBlue": "#6A5ACD",
        "SlateGray": "#708090",
        "SlateGrey": "#708090",
        "Snow": "#FFFAFA",
        "SpringGreen": "#00FF7F",
        "SteelBlue": "#4682B4",
        "Tan": "#D2B48C",
        "Teal": "#008080",
        "Thistle": "#D8BFD8",
        "Tomato": "#FF6347",
        "Turquoise": "#40E0D0",
        "Violet": "#EE82EE",
        "Wheat": "#F5DEB3",
        "White": "#FFFFFF",
        "WhiteSmoke": "#F5F5F5",
        "Yellow": "#FFFF00",
        "YellowGreen": "#9ACD32"
    };
    for (var p in webColors) {
        webColors[p.toLowerCase()] = webColors[p];
    }
    var wc = webColors[input.toLowerCase()];
    if (wc != null)
        return parseColor(wc);
    console.log(input);
    throw Error("'" + input + "' is not a valid color...");
}
// parseColor("steelblue");
parseColor("SteelBlue");
// JSON.stringify(webColors, null, 2);
// JSON.stringify(lcWebColors, null, 2);
//# sourceMappingURL=colorInfluence.js.map

6
投票

虽然kennebec已经基本完成了Kolink的答案,但还有一些改进需要进行。首先,我们可以支持 hsla 和 rgba,这样做时最好始终返回 alpha 值。另一个小的改进是通过将修剪方法应用于传入的参数字符串来实现。

function parseColor(color) {
    color = color.trim().toLowerCase();
    color = _colorsByName[color] || color;
    var hex3 = color.match(/^#([0-9a-f]{3})$/i);
    if (hex3) {
        hex3 = hex3[1];
        return [
            parseInt(hex3.charAt(0),16)*0x11,
            parseInt(hex3.charAt(1),16)*0x11,
            parseInt(hex3.charAt(2),16)*0x11, 1
        ];
    }
    var hex6 = color.match(/^#([0-9a-f]{6})$/i);
    if (hex6) {
        hex6 = hex6[1];
        return [
            parseInt(hex6.substr(0,2),16),
            parseInt(hex6.substr(2,2),16),
            parseInt(hex6.substr(4,2),16), 1
        ];
    }
    var rgba = color.match(/^rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+.*\d*)\s*\)$/i) || color.match(/^rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i);
    if( rgba ) {
        return [rgba[1],rgba[2],rgba[3], rgba[4]===undefined?1:rgba[4]];
    }
    var rgb = color.match(/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i);
    if( rgb ) {
        return [rgb[1],rgb[2],rgb[3],1];
    }
    if(color.indexOf('hsl')== 0)
        return _hslToRgb(color);
}

function _hslToRgb(hsl){
    if(typeof hsl== 'string'){
        hsl= hsl.match(/(\d+(\.\d+)?)/g);
    }
    var sub, h= hsl[0]/360, s= hsl[1]/100, l= hsl[2]/100, a = hsl[3]===undefined?1:hsl[3], t1, t2, t3, rgb, val;
    if(s== 0){
        val= Math.round(l*255);
        rgb= [val, val, val, a];
    }
    else{
        if(l<0.5)
            t2= l*(1 + s);
        else
            t2= l + s - l*s;
        t1 = 2*l - t2;
        rgb = [0, 0, 0];
        for(var i=0; i<3; i++){
            t3 = h + 1/3 * -(i - 1);
            t3 < 0 && t3++;
            t3 > 1 && t3--;
            if (6 * t3 < 1)
                val= t1 + (t2 - t1) * 6 * t3;
            else if (2 * t3 < 1)
                val= t2;
            else if (3*t3<2)
                val = t1 + (t2 - t1) * (2 / 3 - t3) * 6;
            else
                val= t1;
            rgb[i] = Math.round(val*255);
        }
    }
    rgb.push(a);
    return rgb;
}
var _colorsByName = {aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",
    black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",
    chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",
    darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkkhaki:"#bdb76b",
    darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",
    darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",
    deepskyblue:"#00bfff",dimgray:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",
    fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",
    greenyellow:"#adff2f",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred :"#cd5c5c",indigo :"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",
    lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",
    lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",
    lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",
    limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",
    mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",
    mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",
    navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",
    orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",
    peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",red:"#ff0000",rosybrown:"#bc8f8f",
    royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",
    silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",
    tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",
    whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"
};

3
投票

// 这将为您发布的示例返回一个 [red.green,blue] 十进制数组,加上 rgb 百分比。

// 它忽略透明度、hsl 和大多数浏览器支持的扩展颜色名称集:

function getRgb(c){
    c= c.toLowerCase();
    if (/^[a-z]+$/.test(c)){
        var colornames={
            aqua:'#00ffff', black:'#000000', blue:'#0000ff', fuchsia:'#ff00ff',
            gray:'#808080', green:'#008000', lime:'#00ff00', maroon:'#800000',
            navy:'#000080', olive:'#808000', orange:'#ffa500', purple:'#800080',
            red:'#ff0000', silver:'#c0c0c0', teal:'#008080', white:'#ffffff',
            yellow:'#ffff00'
        }
        c= colornames[c];
    }
    if(/^#([a-f0-9]{3}){1,2}$/.test(c)){
        if(c.length== 4){
            c= '#'+[c[1], c[1], c[2], c[2], c[3], c[3]].join('');
        }
        c= '0x'+c.substring(1);
        return [(c>>16)&255, (c>>8)&255, c&255];
    }
    else if(c.indexOf('rgb')== 0){
        c= c.match(/\d+(\.\d+)?%?/g);
        if(c){
            for(var i= 0;i<3;i++){
                if(c[i].indexOf('%')!= -1){
                         c[i]= Math.round(parseFloat(c[i])*2.55);
                    }
                if(c[i]<0) c[i]= 0;
                if(c[i]>255) c[i]= 255;
            }
            return c;
        }
    }
}

//此版本将为大多数颜色字符串返回[red.green,blue]十进制数组,忽略透明度。

function getRgb2(c){
    c= c.toLowerCase();
    var colornames={
        aliceblue:'#f0f8ff', antiquewhite:'#faebd7', aqua:'#00ffff',
        aquamarine:'#7fffd4', azure:'#f0ffff', beige:'#f5f5dc',
        bisque:'#ffe4c4', black:'#000000', blanchedalmond:'#ffebcd',
        blue:'#0000ff', blueviolet:'#8a2be2', brown:'#a52a2a',
        burlywood:'#deb887', cadetblue:'#5f9ea0', chartreuse:'#7fff00',
        chocolate:'#d2691e', coral:'#ff7f50', cornflowerblue:'#6495ed',
        cornsilk:'#fff8dc', crimson:'#dc143c', cyan:'#00ffff',
        darkblue:'#00008b', darkcyan:'#008b8b', darkgoldenrod:'#b8860b',
        darkgray:'#a9a9a9', darkgreen:'#006400', darkkhaki:'#bdb76b',
        darkmagenta:'#8b008b', darkolivegreen:'#556b2f', darkorange:'#ff8c00',
        darkorchid:'#9932cc', darkred:'#8b0000', darksalmon:'#e9967a',
        darkseagreen:'#8fbc8f', darkslateblue:'#483d8b', darkslategray:'#2f4f4f',
        darkturquoise:'#00ced1', darkviolet:'#9400d3', deeppink:'#ff1493',
        deepskyblue:'#00bfff', dimgray:'#696969', dodgerblue:'#1e90ff',
        firebrick:'#b22222', floralwhite:'#fffaf0',
        forestgreen:'#228b22', fuchsia:'#ff00ff', gainsboro:'#dcdcdc',
        ghostwhite:'#f8f8ff', gold:'#ffd700', goldenrod:'#daa520', gray:'#808080',
        green:'#008000', greenyellow:'#adff2f', honeydew:'#f0fff0',
        hotpink:'#ff69b4', indianred:'#cd5c5c', indigo:'#4b0082',
        ivory:'#fffff0', khaki:'#f0e68c', lavender:'#e6e6fa',
        lavenderblush:'#fff0f5', lawngreen:'#7cfc00', lemonchiffon:'#fffacd',
        lightblue:'#add8e6', lightcoral:'#f08080', lightcyan:'#e0ffff',
        lightgoldenrodyellow:'#fafad2', lightgray:'#d3d3d3', lightgreen:'#90ee90',
        lightpink:'#ffb6c1', lightsalmon:'#ffa07a', lightseagreen:'#20b2aa',
        lightskyblue:'#87cefa', lightslategray:'#778899', lightsteelblue:'#b0c4de',
        lightyellow:'#ffffe0', lime:'#00ff00', limegreen:'#32cd32', linen:'#faf0e6',
        magenta:'#ff00ff', maroon:'#800000', mediumaquamarine:'#66cdaa',
        mediumblue:'#0000cd', mediumorchid:'#ba55d3', mediumpurple:'#9370db',
        mediumseagreen:'#3cb371', mediumslateblue:'#7b68ee',
        mediumspringgreen:'#00fa9a', mediumturquoise:'#48d1cc',
        mediumvioletred:'#c71585', midnightblue:'#191970', mintcream:'#f5fffa',
        mistyrose:'#ffe4e1', moccasin:'#ffe4b5', navajowhite:'#ffdead',
        navy:'#000080', oldlace:'#fdf5e6', olive:'#808000', olivedrab:'#6b8e23',
        orange:'#ffa500', orangered:'#ff4500', orchid:'#da70d6',
        alegoldenrod:'#eee8aa', palegreen:'#98fb98', paleturquoise:'#afeeee',
        palevioletred:'#db7093', papayawhip:'#ffefd5', peachpuff:'#ffdab9',
        peru:'#cd853f', pink:'#ffc0cb', plum:'#dda0dd', powderblue:'#b0e0e6',
        purple:'#800080', red:'#ff0000', rosybrown:'#bc8f8f', royalblue:'#4169e1',
        saddlebrown:'#8b4513', salmon:'#fa8072', sandybrown:'#f4a460',
        seagreen:'#2e8b57', seashell:'#fff5ee', sienna:'#a0522d',
        silver:'#c0c0c0', skyblue:'#87ceeb', slateblue:'#6a5acd',
        slategray:'#708090', snow:'#fffafa', springgreen:'#00ff7f',
        steelblue:'#4682b4', tan:'#d2b48c', teal:'#008080', thistle:'#d8bfd8',
        tomato:'#ff6347', turquoise:'#40e0d0', violet:'#ee82ee', wheat:'#f5deb3',
        white:'#ffffff', whitesmoke:'#f5f5f5', yellow:'#ffff00', yellowgreen:'#9acd32'
    }
    if (/^[a-z]+$/.test(c)){
        c= colornames[c];
    }
    if(/^#([a-f0-9]{3}){1,2}$/.test(c)){
        if(c.length== 4){
            c= '#'+[c[1], c[1], c[2], c[2], c[3], c[3]].join('');
        }
        c= '0x'+c.substring(1);
        return [(c>>16)&255, (c>>8)&255, c&255];
    }
    if(c.indexOf('hsl')== 0) return hslToRgb(c);
    else{
        c= c.match(/\d+(\.\d+)?%?/g);
        if(c){
            for(var i= 0;i<3;i++){
                if(c[i].indexOf('%')!= -1) c[i]= parseFloat(c[i])*2.55;
                c[i]= Math.round(c[i]);
                if(c[i]<0) c[i]= 0;
                if(c[i]>255) c[i]= 255;
            }
            return c;
        }
    }
    function hslToRgb(hsl){
        if(typeof hsl== 'string'){
            hsl= hsl.match(/(\d+(\.\d+)?)/g);
        }
        var sub, h= hsl[0]/360, s= hsl[1]/100, l= hsl[2]/100,
        t1, t2, t3, rgb, val;
        if(s== 0){
            val= Math.round(l*255);
            rgb= [val, val, val];
        }
        else{
            if(l<0.5)   t2= l*(1 + s);
            else t2= l + s - l*s;
            t1= 2*l - t2;
            rgb= [0, 0, 0];
            for(var i= 0;i<3;i++){
                t3= h + 1/3*-(i - 1);
                t3<0 && t3++;
                t3>1 && t3--;
                if(6*t3<1) val= t1 +(t2 - t1)*6*t3;
                else if(2*t3<1) val= t2;
                else if(3*t3<2) val= t1 +(t2 - t1)*(2/3 - t3)*6;
                else val= t1;
                rgb[i]= Math.round(val*255);
            }
        }
        return rgb;
    }
}

2
投票

简化@NicolasL 的答案(这又受到@Niet_the_Dark_Absol 的启发)

我得到了这个简单而简短的基于浏览器的解决方案:

function parseCssColor(str) {
    const div = document.createElement("div");
    document.body.appendChild(div);
    div.style.color = str;
    const res = getComputedStyle(div).color.match(/[\.\d]+/g).map(Number);
    div.remove();
    return res;
}


parseCssColor("lightblue")  // [173, 216, 230]
parseCssColor("#663399")    // [102, 51, 153]
parseCssColor("#aa11bb22")  // [170, 17, 187, 0.133]

2
投票

我来这里也是为了同样的问题。但在阅读了所有这些方法(以及它们在所有情况下错误或不起作用的地方)后,我决定去图书馆。

除了解析颜色之外,大多数时候你还想用它做一些事情。

如果像我一样,您对“高效”的定义是“错误更少且开箱即用”,我建议使用 chroma.js

使用

npm install chroma-js
安装它(不是 chrome-js,不是 chroma)

chroma('pink').darken().saturate(2).rgb()

0
投票

对于 hsl 和 rgb 这两种颜色类型都有效:

input.replace(/[a-z%\s\(\)]/g,'').split(',')

0
投票

尝试使用 @Niet_the_Dark_Absol 的答案,使用这个漂亮的

getComputedStyle
hack,我一直无法使其工作,直到将创建的元素附加到 DOM(Chrome 69 和 Firefox 75)。

由于我还希望能够处理 alpha 通道值(透明度),因此我修改了正则表达式并返回了结果。

这是我的功能,如果它可以对任何人有任何帮助:

function colorToRgbParser(cssColor) {
  const div = document.createElement('div');
  div.id = 'for-computed-style';

  div.style.color = cssColor;

  // appending the created element to the DOM
  document.querySelector('body').appendChild(div);

  const match = getComputedStyle(div).color.match(/^rgba?\s*\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d\.\d)\s*)?\)$/i);

  // removing element from the DOM
  document.querySelector('#for-computed-style').remove();

  if (match) {
    // match[0] is regex complete match (e.g. "rgb(0,0,0)"), not a regex capturing group
    let parsedColor = {
      r: match[1],
      g: match[2],
      b: match[3]
    };
    if (match[4]) { // if alpha channel is present
      parsedColor.a = match[4];
    }
    return parsedColor;
  } else {
    throw new Error(`Color ${cssColor} could not be parsed.`);
  }
}

0
投票

/**
 * Created on 1401/6/11 (2022/9/2).
 * @author {@link https://mirismaili.github.io S. Mahdi Mir-Ismaili}
 */

class Color {
  #r = 0
  #g = 0
  #b = 0
  #a = 1
  #red = 0
  #green = 0
  #blue = 0
  #alpha = 100
  #alpha255 = 255
  
  /**
   * @param {RgbInputParams|[number?,number?,number?,number?]|string|number} rgbInputParamsOrRgbArrayOrHexFormatOrRed
   * @param {number} green
   * @param {number} blue
   * @param {number} alpha
   */
  constructor ({
    red = 0, green = 0, blue = 0, alpha = 100, r = red / 255, g = green / 255, b = blue / 255, a = alpha / 100,
  } = {}) { // noinspection JSCheckFunctionSignatures
    this.set(...arguments)
  }
  
  /**
   * @param {RgbInputParams|[number?,number?,number?,number?]|string|number} rgbInputParamsOrRgbArrayOrHexFormatOrRed
   * @param {number} green
   * @param {number} blue
   * @param {number} alpha
   */
  set ({
    red = 0, green = 0, blue = 0, alpha = 100, r = red / 255, g = green / 255, b = blue / 255, a = alpha / 100,
  } = {}) {
    const input = arguments[0] ?? {r: 0, g: 0, b: 0, a: 1}
    const inputType = typeof input
    
    if (inputType === 'object') {
      if (input instanceof Array) {
        this.rgb = input
        return this
      }
      
      this.r = r
      this.g = g
      this.b = b
      this.a = a
      return this
    }
    
    if (inputType === 'number') { // noinspection JSValidateTypes
      this.RGB = arguments
      return this
    }
    
    if (inputType !== 'string') throw Error(`Unsupported color format: ${input}`)
    
    if (input.startsWith('#')) { // hex (`#123456`) format:
      this.hex = input
      return this
    }
    
    const match = input.match(/^rgba?\s*\(\s*(.+)\s*\)$/i) // https://regex101.com/r/TvtRCL/1
    if (match) { // `rgb[a](...)` format:
      const values = match[1].split(/[ ,/]+/)
      this.RGB = values.slice(0, 3).map(v => +v)
      const aa = values[3]
      if (!aa) this.a = 1
      else if (aa.endsWith('%')) this.alpha = +aa.slice(0, -1)
      else this.a = +aa
      return this
    }
    
    if (input in WEB_COLORS) {
      this.name = input
      return this
    }
    throw Error(`Unsupported color format: ${input}`)
  }
  
  get r () { return this.#r }
  get g () { return this.#g }
  get b () { return this.#b }
  get a () { return this.#a }
  get red () { return this.#red }
  get green () { return this.#green }
  get blue () { return this.#blue }
  get alpha () { return this.#alpha }
  get alpha255 () { return this.#alpha255 }
  get rgb () { return [this.#r, this.#g, this.#b, this.#a] }
  get RGB () { return [this.#red, this.#green, this.#blue, this.#alpha] }
  get value () { // `>>> 0` is to make the result unsigned. See: https://stackoverflow.com/a/54030756/5318303
    return (this.#red << 24 >>> 0) + (this.#green << 16) + (this.#blue << 8) + this.#alpha255
  }
  get hex () {
    const hex = this.value.toString(16).padStart(8, '0')
    return this.alpha255 < 255 ? `#${hex}` : `#${hex.slice(0, -2)}`
  }
  get name () {return REVERSE_WEB_COLORS[this.hex]}
  
  set r (r) {
    this.#r = r
    this.#red = Math.round(r * 255)
  }
  set g (g) {
    this.#g = g
    this.#green = Math.round(g * 255)
  }
  set b (b) {
    this.#b = b
    this.#blue = Math.round(b * 255)
  }
  set a (a) {
    this.#alpha = Math.round(a * 100)
    this.#a = a
    this.#alpha255 = Math.round(a * 255)
  }
  set red (red) {
    this.#r = red / 255
    this.#red = red
  }
  set green (green) {
    this.#g = green / 255
    this.#green = green
  }
  set blue (blue) {
    this.#b = blue / 255
    this.#blue = blue
  }
  set alpha (alpha) {
    this.#a = alpha / 100
    this.#alpha = alpha
    this.#alpha255 = Math.round(this.#a * 255)
  }
  set alpha255 (alpha255) {
    this.#a = alpha255 / 255
    this.#alpha255 = alpha255
    this.#alpha = Math.round(this.#a * 100)
  }
  set rgb ([r, g, b, a]) {
    if (typeof r === 'number') this.r = r
    if (typeof g === 'number') this.g = g
    if (typeof b === 'number') this.b = b
    if (typeof a === 'number') this.a = a
  }
  set RGB ([red, green, blue, alpha]) {
    if (typeof red === 'number') this.red = red
    if (typeof green === 'number') this.green = green
    if (typeof blue === 'number') this.blue = blue
    if (typeof alpha === 'number') this.alpha = alpha
  }
  set value (value) { // https://jsben.ch/ZJB9W
    this.alpha255 = value % 0x100
    this.blue = (value >>>= 8) % 0x100
    this.green = (value >>>= 8) % 0x100
    this.red = (value >>> 8) % 0x100
  }
  set hex (hexFormatColor) {
    let hex = hexFormatColor.slice(1)
    // noinspection FallThroughInSwitchStatementJS
    switch (hex.length) { // #123 | #1234 | #123456 | #12345678
      case 3:
        hex += 'f' // default `alpha`
      case 4:
        hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2] + hex[3] + hex[3]
        break
      case 6:
        hex += 'ff' // default `alpha`
      case 8:
        break
      default:
        throw Error(`Unsupported color format (${hexFormatColor}). The length of hex string must be 3 or 4 or 6 or 8.`)
    }
    this.value = parseInt(hex, 16)
  }
  set name (input) {
    const hexFormatColor = WEB_COLORS[input]
    this.value = (parseInt(hexFormatColor.slice(1), 16) << 8 >>> 0) + 0xFF
  }
  
  toString () { // noinspection JSCheckFunctionSignatures
    const hex = this.hex
    const colorName = this.name
    
    return hex + (this.alpha255 < 255
                  ? ` rgb(${this.#red} ${this.#green} ${this.#blue} / ${this.#alpha}%)`
                  : ` rgb(${this.#red} ${this.#green} ${this.#blue})`
    ) + (colorName ? ` "${colorName}"` : '')
  }
}

// Uncomment `await` in your module:
/*await*/ import('util').then((util) => {
  Color.prototype[util.inspect.custom] = function () {
    return this.toString()
  }
}).catch(() => {}) // Ignore `import` error to sure it works properly in both node and browser environments

/**
 * @typedef {Object} RgbInputParams
 * @property {number} [red=0] An integer in `[0, 255]` interval
 * @property {number} [green=0] An integer in `[0, 255]` interval
 * @property {number} [blue=0] An integer in `[0, 255]` interval
 * @property {number} [alpha=0] An integer in `[0, 100]` interval
 * @property {number} [r=red/255] An alternative for **red** channel as a number in `[0, 1]` interval
 * @property {number} [g=green/255] An alternative for **green** channel as a number in `[0, 1]` interval
 * @property {number} [b=blue/255] An alternative for **blue** channel as a number in `[0, 1]` interval
 * @property {number} [a=alpha/100] An alternative for **alpha** channel as a number in `[0, 1]` interval
 */

const WEB_COLORS = {
  black: '#000000',
  silver: '#c0c0c0',
  gray: '#808080',
  white: '#ffffff',
  maroon: '#800000',
  red: '#ff0000',
  purple: '#800080',
  fuchsia: '#ff00ff',
  green: '#008000',
  lime: '#00ff00',
  olive: '#808000',
  yellow: '#ffff00',
  navy: '#000080',
  blue: '#0000ff',
  teal: '#008080',
  aqua: '#00ffff',
  aliceblue: '#f0f8ff',
  antiquewhite: '#faebd7',
  aquamarine: '#7fffd4',
  azure: '#f0ffff',
  beige: '#f5f5dc',
  bisque: '#ffe4c4',
  blanchedalmond: '#ffebcd',
  blueviolet: '#8a2be2',
  brown: '#a52a2a',
  burlywood: '#deb887',
  cadetblue: '#5f9ea0',
  chartreuse: '#7fff00',
  chocolate: '#d2691e',
  coral: '#ff7f50',
  cornflowerblue: '#6495ed',
  cornsilk: '#fff8dc',
  crimson: '#dc143c',
  cyan: '#00ffff',
  darkblue: '#00008b',
  darkcyan: '#008b8b',
  darkgoldenrod: '#b8860b',
  darkgray: '#a9a9a9',
  darkgreen: '#006400',
  darkgrey: '#a9a9a9',
  darkkhaki: '#bdb76b',
  darkmagenta: '#8b008b',
  darkolivegreen: '#556b2f',
  darkorange: '#ff8c00',
  darkorchid: '#9932cc',
  darkred: '#8b0000',
  darksalmon: '#e9967a',
  darkseagreen: '#8fbc8f',
  darkslateblue: '#483d8b',
  darkslategray: '#2f4f4f',
  darkslategrey: '#2f4f4f',
  darkturquoise: '#00ced1',
  darkviolet: '#9400d3',
  deeppink: '#ff1493',
  deepskyblue: '#00bfff',
  dimgray: '#696969',
  dimgrey: '#696969',
  dodgerblue: '#1e90ff',
  firebrick: '#b22222',
  floralwhite: '#fffaf0',
  forestgreen: '#228b22',
  gainsboro: '#dcdcdc',
  ghostwhite: '#f8f8ff',
  gold: '#ffd700',
  goldenrod: '#daa520',
  greenyellow: '#adff2f',
  grey: '#808080',
  honeydew: '#f0fff0',
  hotpink: '#ff69b4',
  indianred: '#cd5c5c',
  indigo: '#4b0082',
  ivory: '#fffff0',
  khaki: '#f0e68c',
  lavender: '#e6e6fa',
  lavenderblush: '#fff0f5',
  lawngreen: '#7cfc00',
  lemonchiffon: '#fffacd',
  lightblue: '#add8e6',
  lightcoral: '#f08080',
  lightcyan: '#e0ffff',
  lightgoldenrodyellow: '#fafad2',
  lightgray: '#d3d3d3',
  lightgreen: '#90ee90',
  lightgrey: '#d3d3d3',
  lightpink: '#ffb6c1',
  lightsalmon: '#ffa07a',
  lightseagreen: '#20b2aa',
  lightskyblue: '#87cefa',
  lightslategray: '#778899',
  lightslategrey: '#778899',
  lightsteelblue: '#b0c4de',
  lightyellow: '#ffffe0',
  limegreen: '#32cd32',
  linen: '#faf0e6',
  magenta: '#ff00ff',
  mediumaquamarine: '#66cdaa',
  mediumblue: '#0000cd',
  mediumorchid: '#ba55d3',
  mediumpurple: '#9370db',
  mediumseagreen: '#3cb371',
  mediumslateblue: '#7b68ee',
  mediumspringgreen: '#00fa9a',
  mediumturquoise: '#48d1cc',
  mediumvioletred: '#c71585',
  midnightblue: '#191970',
  mintcream: '#f5fffa',
  mistyrose: '#ffe4e1',
  moccasin: '#ffe4b5',
  navajowhite: '#ffdead',
  oldlace: '#fdf5e6',
  olivedrab: '#6b8e23',
  orange: '#ffa500',
  orangered: '#ff4500',
  orchid: '#da70d6',
  palegoldenrod: '#eee8aa',
  palegreen: '#98fb98',
  paleturquoise: '#afeeee',
  palevioletred: '#db7093',
  papayawhip: '#ffefd5',
  peachpuff: '#ffdab9',
  peru: '#cd853f',
  pink: '#ffc0cb',
  plum: '#dda0dd',
  powderblue: '#b0e0e6',
  rosybrown: '#bc8f8f',
  royalblue: '#4169e1',
  saddlebrown: '#8b4513',
  salmon: '#fa8072',
  sandybrown: '#f4a460',
  seagreen: '#2e8b57',
  seashell: '#fff5ee',
  sienna: '#a0522d',
  skyblue: '#87ceeb',
  slateblue: '#6a5acd',
  slategray: '#708090',
  slategrey: '#708090',
  snow: '#fffafa',
  springgreen: '#00ff7f',
  steelblue: '#4682b4',
  tan: '#d2b48c',
  thistle: '#d8bfd8',
  tomato: '#ff6347',
  turquoise: '#40e0d0',
  violet: '#ee82ee',
  wheat: '#f5deb3',
  whitesmoke: '#f5f5f5',
  yellowgreen: '#9acd32',
}

const REVERSE_WEB_COLORS = Object.fromEntries(Object.entries(WEB_COLORS).map(([k, v]) => [v, k]))

new Color('#123')
new Color('#1234')
new Color('#123456')
new Color('#12345678')

new Color('rgb(32, 98, 101)')
new Color('rgb(32 98 101 / 86%)')
new Color('rgba(32 98 101 / .86)')

new Color('blue')
new Color('darkgreen')

new Color({r: 0.4, g: 0.2, b: 0.9})
new Color([0.4, 0.2, 0.9])
new Color({red: 45, green: 142, blue: 255})
new Color(45, 142, 255)

let color = new Color()
color.value = 0x12345678 // '#1234567'

// outputs:
color = new Color('#83a0bfa0')
console.log(color)
console.log(color.toString())
console.log(color.hex)
console.log(color.value)
const {r, g, b, a, red, green, blue, alpha} = color
console.log({r, g, b, a, red, green, blue, alpha})

color = new Color('#ff0000')
console.log(color)
console.log(color.toString())
console.log(color.hex)
console.log(color.rgb)
console.log(color.RGB)
console.log(color.name)

将其安装为 NPM 模块:

npm i smart-color
import Color from 'smart-color/Color.js'

// ...

0
投票

Nitsan BenHanoch 的答案的变体,它始终返回不透明度在 0 到 255 范围内的 RGBA,可由 ImageData 数据 Uint8ClampedArray 使用

function parseCssColor(canvas, str) {
    canvas.style.color = str;
    const res = getComputedStyle(canvas).color.match(/[\.\d]+/g).map(Number);
    if (res.length > 3) {
        // adjust opacity range from 0 to 1 to 0 to 255
        res[3] = Math.round(res[3] * 256);
    } else {
        // opaque opacity
        res.push(255);
    }
    return res;
}

-1
投票
var input = '#FFF';
var color = input.toLowerCase();
var hex = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'];
var rgb = [];
if(/#/.test(color))
    if(color.length==4){
        var parsed = color.match(/\w/g);
        rgb = [
            hex.indexOf(parsed[0])*16+hex.indexOf(parsed[0]),
            hex.indexOf(parsed[1])*16+hex.indexOf(parsed[1]),
            hex.indexOf(parsed[2])*16+hex.indexOf(parsed[2])
        ]
    }else{
        var parsed = color.match(/\w{2}/g);
        rgb = [
            hex.indexOf(parsed[0][0])*16+hex.indexOf(parsed[0][1]),
            hex.indexOf(parsed[1][0])*16+hex.indexOf(parsed[1][1]),
            hex.indexOf(parsed[2][0])*16+hex.indexOf(parsed[2][1])
        ]
    }
else if(/(rgb)/.test(color))
    rgb = color.match(/\d+/g);
else{
    //Here you define all the colors, like 'blue': [0,0,255]
}

例如,如果您尝试获取元素的背景颜色,您可以使用以下命令:

var bg = getComputedStyle(myElem,null).getPropertyValue('background-color');
var rgb = match(/\d+/g).slice(0,3);
© www.soinside.com 2019 - 2024. All rights reserved.