What is the most efficient way to parse a CSS color in JavaScript?

后端 未结 9 1895
甜味超标
甜味超标 2020-12-06 04:36

Given a string of a valid CSS color value:

  • #fff
  • #ffffff
  • white
  • rgb(255, 255, 255)

Need to get an array of numbers of t

相关标签:
9条回答
  • 2020-12-06 04:55

    // This will return a [red.green,blue] decimal array for the samples you posted, plus rgb percentages.

    // It ignores transparency, hsl and the extended set of color names most browsers support:

    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;
            }
        }
    }
    

    //This version will return a [red.green,blue] decimal array for most color strings, ignoring transparency.

    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;
        }
    }
    
    0 讨论(0)
  • 2020-12-06 04:56

    While kennebec has mostly completed Kolink's answer, there are some improvements to be made. Firstly, we can support hsla and rgba, and in doing so it is best to always return an alpha value. Another minor improvement is made by applying the trim method to the incoming argument string.

    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"
    };
    
    0 讨论(0)
  • 2020-12-06 05:04

    For both type of colors hsl and rgb this works:

    input.replace(/[a-z%\s\(\)]/g,'').split(',')
    
    0 讨论(0)
  • 2020-12-06 05:07

    Necromancing.
    For anybody that actually needs it, here's fully working and feature-complete code.
    Think of it as complement to the answer of "Niet the Dark Absol"
    Cheers.

    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
    
    0 讨论(0)
  • 2020-12-06 05:08

    For HTML5 compatible browsers I write a single pixel into a <canvas> using the specified value, and read back the rgba quad.

    For performance I memoize this function so that repeated calls for the same colour string don't have to perform the canvas operations.

    EDIT updated for ES6 and to remove jQuery dependency

    EDIT (1j01) added invalid color detection, and a function that supports passing a fallback color

    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]
    
    0 讨论(0)
  • 2020-12-06 05:08

    Quicker and more efficient way

    In addition to @NiettheDarkAbsol 's correct answer, there are some aspects:

    • backgroundColor could be rgb( 3 values ) or rgba( 4 values)

    • match function is nice but using regular expression is expensive! Whenever possible, prefer split instead.

    This function is simplier and quicker:

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

    Ok returned values are still strings, and they contains unwanted spaces, but if used in mathematical expression, they would work correctly!

    At all I prefer this anyway: They may be included as is:

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

    Support #RnGnBn format, for IEx as commented by Emile Bergeron

    There is a small and quick function working with rgb(r,g,b), rgba(r,g,b,a), #RGB, #RRGGBB and #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);
    }
    

    Demo

    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){
            document.getElementById('out').innerHTML+=
            parseColor(color)+" = parseColor(\""+color+"\");<br>";
        }
    );
    <pre id="out" style="font-size:1.2em;"></pre>

    0 讨论(0)
提交回复
热议问题