如何在jQuery/JavaScript中比较两个颜色值?

20
我使用 jQuery 中的 .css('color') 方法来获取颜色值,然后我知道应该是哪种颜色。
我如何比较从 jQuery 获取的颜色值与例如黑色的颜色值?

你想要比较什么?亮度、色调、饱和度?你的目标是什么? - Tatu Ulmanen
我需要知道文本字段是否有真正的数据,因为现在它在标签上的颜色与用户实际输入的颜色不同... - newbie
7个回答

21

以下是一种使用 jQuery 可以在所有浏览器上运行的方法:

  1. 在 HTML 页面上创建一个隐藏的 div 元素 <div id="dummy" style="display:none;"></div>。 (使用 JQuery 动态创建虚拟元素不能适用于命名颜色)
  2. 将虚拟元素的颜色设置为预期的颜色,例如 $('#dummy').css('color','black');
  3. 将虚拟元素的颜色与你想要检查的元素进行比较

例如:

if($('#element').css('color') === $('#dummy').css('color')) {
  //do something
}

1
这应该是正确的答案。这是唯一的方法,您可以确信像#c0cc00和RGB(192, 204, 0)这样的内容会进行比较。 - Ed Bayiates
我认为这也不可靠。在最新的Chrome浏览器中,我的虚拟div返回了“white”,但我比较的元素返回了“rgb(255,255,255)”。 - Daniel Howard
你使用的操作系统是什么?你有你所做的示例代码吗? - Mike
有些浏览器会以你提供的格式返回给你。(现在不多见了,但是...) - T.J. Crowder
在经过5-6个小时的努力之后,我很高兴终于找到了这个。你会认为他们现在应该有一个更好的解决方案。非常感谢你,希望我能给你两个赞! - madprogramer
@DanielHoward 对于Chrome浏览器而言,虚拟元素是否附加到渲染的DOM上是有区别的。如果未附加,则.css()返回原始样式值字符串;如果已附加,则会转换为rgb()格式。 - ccprog

17

关于这个问题...

if ($('#element').css('color') == 'rgb(0, 0, 0)')
{
    // do something
}

将0、0、0替换为颜色值中你想要比较的红、绿、蓝值。

.css() jQuery API


3
请注意,这种方法并不总是适用于Internet Explorer浏览器,因为它会返回原始值。因此,可能是从3位或6位十六进制值到命名颜色的任何值。 - Bruce van der Kooij
1
是的,我不确定,但我认为jQuery抽象出了浏览器之间的差异? - Andy Shellam
3
有没有更多独立于实现的解决方案?即使在RGB值之间稍微改变一下空格,也会搞乱这个等式,更不用说十六进制表示法或者简单的单词表示法,比如白色或黑色。有人有主意吗? - Gerard

5
我曾遇到过类似问题,需要切换一个元素的背景颜色。我是这样解决的:
var color_one = "#FFA500";
var color_two = "#FFFF00";

function toggle_color(elem){
    var bgcolor = elem.css("background-color");
    elem.css("background-color", color_one);     // try new color
    if(bgcolor == elem.css("background-color"))  // check if color changed
        elem.css("background-color", color_two); // if here means our color was color_one
}

我喜欢这个,虽然我仍然认为为了更加健壮,最好使用全局变量来跟踪状态...所以我打算在我的当前项目中这样做。检查颜色更容易,但是出现错误的机会太多了。 - eselk
不错,但它不能与CSS3过渡一起使用,虽然很好。我将尝试将颜色值转换为常量值。 - Lzh

3
这是我按照Mike的答案编写的实现,只有一个函数。
function compareColors(left, right) {
    // Create a dummy element to assign colors to.
    var dummy = $('<div/>');

    // Set the color to the left color value, and read it back.
    $(dummy).css('color', left);
    var adjustedLeft = $(dummy).css('color');

    // Set the color to the right color value, and read it back.
    $(dummy).css('color', right);
    var adjustedRight = $(dummy).css('color');

    // Both colors are now adjusted to use the browser's internal format,
    // so we can compare them directly.
    return adjustedLeft == adjustedRight;
}

您不需要将元素实际添加到DOM中即可使其工作。在IE8、IE10、FF、Chrome和Safari中进行了测试。


简单明了。这对比较rgb(r, g, b)和#ffffff值非常有用。 - armitus

2
CSS颜色可以以许多格式出现 - rgbrgba#hex,几乎不支持的#hexalpha,臭名昭著的命名颜色和特殊的transparent。 要比较任何颜色与任何颜色,您需要首先将它们标准化。 在这里(gist)这里(SO答案)找到的colorValues函数将始终为您提供数字值的[r,g,b,a]数组。
然后您可以像这样进行比较:
var sameColor = colorValues(color1).join(',') === colorValues(color2).join(',');

颜色值函数
// return array of [r,g,b,a] from any valid color. if failed returns undefined
function colorValues(color)
{
    if (color === '')
        return;
    if (color.toLowerCase() === 'transparent')
        return [0, 0, 0, 0];
    if (color[0] === '#')
    {
        if (color.length < 7)
        {
            // convert #RGB and #RGBA to #RRGGBB and #RRGGBBAA
            color = '#' + color[1] + color[1] + color[2] + color[2] + color[3] + color[3] + (color.length > 4 ? color[4] + color[4] : '');
        }
        return [parseInt(color.substr(1, 2), 16),
            parseInt(color.substr(3, 2), 16),
            parseInt(color.substr(5, 2), 16),
            color.length > 7 ? parseInt(color.substr(7, 2), 16)/255 : 1];
    }
    if (color.indexOf('rgb') === -1)
    {
        // convert named colors
        var temp_elem = document.body.appendChild(document.createElement('fictum')); // intentionally use unknown tag to lower chances of css rule override with !important
        var flag = 'rgb(1, 2, 3)'; // this flag tested on chrome 59, ff 53, ie9, ie10, ie11, edge 14
        temp_elem.style.color = flag;
        if (temp_elem.style.color !== flag)
            return; // color set failed - some monstrous css rule is probably taking over the color of our object
        temp_elem.style.color = color;
        if (temp_elem.style.color === flag || temp_elem.style.color === '')
            return; // color parse failed
        color = getComputedStyle(temp_elem).color;
        document.body.removeChild(temp_elem);
    }
    if (color.indexOf('rgb') === 0)
    {
        if (color.indexOf('rgba') === -1)
            color += ',1'; // convert 'rgb(R,G,B)' to 'rgb(R,G,B)A' which looks awful but will pass the regxep below
        return color.match(/[\.\d]+/g).map(function (a)
        {
            return +a
        });
    }
}

0

实际上,我尝试了Charlie Kilian的答案。由于某种原因,当您尝试使用'rgb(0,0,0)'值设置.css('color')时,它不起作用。

我不知道为什么。在控制台中完美运行。也许是因为我的比较函数在javascript对象中,存在某种上下文问题或引用问题。无论如何,最终我感到沮丧,并编写了自己的函数,以比较两种颜色,而不考虑格式,并且不创建任何元素或依赖于jQuery。该函数接受HEX和RGB值。

它可能可以优化,但我现在真的没有时间。希望这对某人有所帮助,它是纯javascript。

var compareColors= function (left, right) {
       var l= parseColor(left);
        var r=parseColor(right);
        if(l !=null && r!=null){
           return l.r == r.r && l.g == r.g && l.b == r.b;
        }else{
            return false;
        }
        function parseColor(color){
           if(color.length==6 || color.length==7){
                //hex color
               return {
                    r:hexToR(color),
                    g:hexToG(color),
                    b:hexToB(color)
                }
            }else if(color.toLowerCase().indexOf('rgb')>-1){
              var arr
                var re = /\s*[0-9]{1,3}\s*,\s*[0-9]{1,3}\s*,\s*[0-9]{1,3}\s*/gmi;
                var m;

                if ((m = re.exec(color)) !== null) {
                    if (m.index === re.lastIndex) {
                        re.lastIndex++;
                    }
                    // View your result using the m-variable.
                    // eg m[0] etc.
                    arr = m[0].split(',');
                    return {
                        r: parseInt(arr[0].trim()),
                        g: parseInt(arr[1].trim()),
                        b: parseInt(arr[2].trim())
                    }
                }else{
                  return null;
                }

            } else{
                return null;
            }
            function hexToR(h) {return parseInt((cutHex(h)).substring(0,2),16)}
            function hexToG(h) {return parseInt((cutHex(h)).substring(2,4),16)}
            function hexToB(h) {return parseInt((cutHex(h)).substring(4,6),16)}
            function cutHex(h) {return (h.charAt(0)=="#") ? h.substring(1,7):h}
        }
    }

以下这些函数我从www.javascripter.net中获取。

            function hexToR(h) {return parseInt((cutHex(h)).substring(0,2),16)}
            function hexToG(h) {return parseInt((cutHex(h)).substring(2,4),16)}
            function hexToB(h) {return parseInt((cutHex(h)).substring(4,6),16)}
            function cutHex(h) {return (h.charAt(0)=="#") ? h.substring(1,7):h}

0

修改自Katie Kilian的代码,但不需要使用jQuery

<div id="dummy"></div>
function compareColors(left, right) {
    // Create a dummy element to assign colors to.
    document.getElementById('dummy').style.background = left;
    var adjustedLeft = document.getElementById('dummy').style.background;

    // Set the color to the right color value, and read it back.
    document.getElementById('dummy').style.background = right;
    var adjustedRight = document.getElementById('dummy').style.background;

    // Both colors are now adjusted to use the browser's internal format,
    // so we can compare them directly.
    return adjustedLeft == adjustedRight;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接