【问题标题】:What is the most efficient way to parse a CSS color in JavaScript?在 JavaScript 中解析 CSS 颜色的最有效方法是什么?
【发布时间】:2012-06-19 13:27:12
【问题描述】:

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

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

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

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

【问题讨论】:

  • 有一些小库可用,例如:github.com/deanm/css-color-parser-js
  • @Timmmm 当浏览器公开了一个完美的 CSS 颜色解析器时,我为什么要移植该代码?!
  • 因为它不会直接暴露它,尽管div 技巧在大多数情况下可能是可以接受的。 OP 确实要求最有效的 方式,但几乎可以肯定是自己解析它。

标签: javascript css performance parsing colors


【解决方案1】:
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() 格式。把它拿回来,读出来。

【讨论】:

  • 如果正则表达式不匹配,则返回的数组中不会有任何值,因此访问数组的第 [1] 个元素会引发错误。在检查 m 是否不为 null 后,您需要访问该元素。
  • 确实如此。也许做m = ({massive colour map here})[input]; if( m) return m; return [0,0,0];。或者从该函数中抛出一个错误,因为要获得这个条件,任何测试都不应该匹配。
  • 另外,rgba 样式的正则表达式匹配也返回数组的 [0] 元素,这意味着它会输出类似:['rgb(5,10,15)', '5' , '10', '15'],所以你要确保只返回新数组中的第 1、2、3 个元素,并省略第 0 个。
  • @Kolink,“我不知道我为什么要费心写这些。”嗯...因为你想成名并永远活着? :) 谢谢你的回复!
  • 很抱歉纠缠你更正,但你甚至没有考虑我为什么这样做,就把我的修复恢复了。
【解决方案2】:

对于兼容 HTML5 的浏览器,我使用指定的值将单个像素写入 <canvas>,然后读回 rgba 四边形。

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

EDIT 为 ES6 更新并移除 jQuery 依赖

EDIT (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]

【讨论】:

  • 这是jquery,不是javascript
  • @F.Hauri 这里唯一的 jQuery 特定函数是 $.makeArray,这只是因为 Array 构造函数被破坏(它将单个值视为长度,但多个值作为初始值)
  • @F.Hauri 我现在已经更新它以删除该依赖项
  • 添加 memoize 的方法。一个很好的实现它对使它成为一个非常完整的答案大有帮助!
  • OP 要求一种快速的方法来做到这一点。创建画布比解析它要慢得多。记忆是隐藏它很慢的一个不好的解决方法。如果您想避免自己编写解析器(这相当复杂),那么 Niet the Dark Absol 的 div 解决方案将比 canvas 快得多。
【解决方案3】:

更快更高效的方式

除了@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(",");

按照Emile Bergeron's comment 的建议支持#RnGnBn 形式(IEx)

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>

【讨论】:

  • 少写多做
  • 虽然我不必支持它们,但 IE7 和 IE8 返回颜色的 HEX 值而不是 RGB 格式。
  • @EmileBergeron 答案已编辑,添加了解析 #XXX#XXXXXX#XXXXXXXXX 的非常短的脚本。
【解决方案4】:

虽然 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"
};

【讨论】:

    【解决方案5】:

    // 这将为您发布的样本返回一个 [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;
        }
    }
    

    【讨论】:

    • 普通文本前的// 是怎么回事?习惯的力量?
    【解决方案6】:

    死灵术。
    对于任何真正需要它的人,这里有完整的工作和功能完整的代码。
    将其视为对“Niet the Dark Absol”答案的补充
    干杯。

    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
    

    【讨论】:

    • 一些注意事项: 1. 使用let 而不是var;或者更好的是,您可以在这里大量使用const。 2. 您不再需要在函数顶部声明变量。这不是 1998 年。 3. 你的小写逻辑全错了。例如。 BLUE 不起作用,但它应该起作用。您应该在 lookup 上将颜色小写,不要只将所有小写名称添加到地图中。 IE。 const we = webColors[input.toLowerCase()].
    • 支持作为唯一一个实际包含颜色名称的人。
    【解决方案7】:

    简化@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]
    

    【讨论】:

      【解决方案8】:

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

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

      【讨论】:

        【解决方案9】:

        用这个漂亮的getComputedStyle hack 尝试@Niet_the_Dark_Absol 的答案,直到将创建的元素(Chrome 69 和 Firefox 75)附加到 DOM 之前,我一直无法使其工作。

        由于我还希望能够处理 Alpha 通道值(透明度),所以我修改了 Regex 并返回了结果。

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

        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.`);
          }
        }
        

        【讨论】:

        • 这实际上是一个很好的解决方案,但是如果您只使用正则表达式 /\d+/g 可以节省大量代码(如果您愿意,可以应用 .map(Number))
        【解决方案10】:

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

        除了在大多数情况下解析颜色之外,您还想对它做一些事情。

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

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

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

        【讨论】:

          【解决方案11】:
          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);
          

          【讨论】:

          • hex.indexOf(parsed[0]) ha 这是一种非常有趣(而且很糟糕!)的方法。
          猜你喜欢
          • 1970-01-01
          • 2013-03-23
          • 2011-03-15
          • 1970-01-01
          • 1970-01-01
          • 2011-12-04
          • 2013-06-23
          • 2018-01-07
          • 1970-01-01
          相关资源
          最近更新 更多