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

Tri*_*Gao 18 javascript css performance parsing colors

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

  • #FFF
  • #FFFFFF
  • 白色
  • rgb(255,255,255)

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

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

Nie*_*sol 30

function parseColor(input) {
    var m;
Run Code Online (Sandbox Code Playgroud)

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

    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
        ];
    }
Run Code Online (Sandbox Code Playgroud)

那是一个.现在为完整的六位数格式:

    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)
        ];
    }
Run Code Online (Sandbox Code Playgroud)

现在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]];
    }
Run Code Online (Sandbox Code Playgroud)

或者,您也可以添加对rgba格式的支持,甚至hsl/ hsla如果您添加HSL2RGB转换功能.

最后,命名颜色.

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

并关闭功能:

}
Run Code Online (Sandbox Code Playgroud)

实际上,我不知道为什么我一直在写这些.我刚刚注意到你指定"假设一个主要的浏览器",我假设这也意味着"最新"?如果是这样...

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.");
}
Run Code Online (Sandbox Code Playgroud)

最新的浏览器会将任何给定的颜色转换rgb()为其计算样式的格式.把它拿回来,然后把它读出来.

  • 很抱歉纠缠您进行更正,但是您甚至没有考虑我最初为什么这样做就在那里恢复了我的修复。 (2认同)

Aln*_*tak 17

对于HTML5兼容的浏览器,我<canvas>使用指定的值将一个像素写入a ,并回读rgba四元组.

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

针对ES6更新了EDIT并删除了jQuery依赖项

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]
Run Code Online (Sandbox Code Playgroud)


F. *_*uri 14

更快捷,更有效的方式

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

  • backgroundColor可以是rgb( 3 values )或rgba( 4 values)

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

此功能更简单,更快捷:

function parseColor(input) {
    return input.split("(")[1].split(")")[0].split(",");
}
Run Code Online (Sandbox Code Playgroud)

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

毕竟我更喜欢这样:它们可能包括在内:

var bgColors = document.getElementById('myDiv').
                 backgroundColor.split("(")[1].split(")")[0].split(",");
Run Code Online (Sandbox Code Playgroud)

支持#RnGnBn格式,由Emile Bergeron评论的 IEx

有一个小而快速的功能与工作rgb(r,g,b),#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(Math.round);
}
Run Code Online (Sandbox Code Playgroud)

演示

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(Math.round);
}

["rgb(123,45,67)","rgb( 123, 45 , 67 )","#F70","#FF7700","#FFF777000",
 "#FF8000","#FFF800000","#F80"].forEach(
    function(color){
    	document.getElementById('out').innerHTML+=
        parseColor(color)+" = parseColor(\""+color+"\");<br>";
    }
);
Run Code Online (Sandbox Code Playgroud)
<pre id="out" style="font-size:1.2em;"></pre>
Run Code Online (Sandbox Code Playgroud)


Ste*_*ger 7

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

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


Ada*_*art 5

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

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"
};
Run Code Online (Sandbox Code Playgroud)