Javascript 如何检查十六进制颜色是否为;太黑了;?

Javascript 如何检查十六进制颜色是否为;太黑了;?,javascript,colors,Javascript,Colors,我试图评估颜色选择器选择的颜色的黑暗度,看看它是否“太黑”,如果是,将其设置为白色。我想我可以使用十六进制值的第一个字符来完成这个任务。它在工作,但它也在转换一些合法的“浅”色 我有这样做的代码: if (lightcolor.substring(0,3) == "#00"|| lightcolor.substring(0,3) == "#010"){ lightcolor="#FFFFFF"; color=lightcolor;

我试图评估颜色选择器选择的颜色的黑暗度,看看它是否“太黑”,如果是,将其设置为白色。我想我可以使用十六进制值的第一个字符来完成这个任务。它在工作,但它也在转换一些合法的“浅”色

我有这样做的代码:

        if (lightcolor.substring(0,3) == "#00"|| lightcolor.substring(0,3) == "#010"){
            lightcolor="#FFFFFF";
            color=lightcolor;
        }

必须有一种更有效的十六进制数学方法才能知道颜色已经超出了一定的黑暗程度?例如,如果lightcolor+“某些十六进制值”,则必须分别提取三个RGB分量,然后使用标准公式将结果RGB值转换为其感知亮度

假设颜色为六个字符:

var c = c.substring(1);      // strip #
var rgb = parseInt(c, 16);   // convert rrggbb to decimal
var r = (rgb >> 16) & 0xff;  // extract red
var g = (rgb >>  8) & 0xff;  // extract green
var b = (rgb >>  0) & 0xff;  // extract blue

var luma = 0.2126 * r + 0.7152 * g + 0.0722 * b; // per ITU-R BT.709

if (luma < 40) {
    // pick a different colour
}
var c=c.substring(1);//剥落#
var rgb=parseInt(c,16);//将rrggbb转换为十进制
var r=(rgb>>16)&0xff;//萃取红
变量g=(rgb>>8)&0xff;//萃绿
变量b=(rgb>>0)&0xff;//萃取蓝
var luma=0.2126*r+0.7152*g+0.0722*b;//根据ITU-R BT.709
如果(亮度<40){
//选择不同的颜色
}
编辑

自2014年5月以来,
tinycolor
现在有了一个
getBrightness()
功能,尽管使用了CCIR601加权因子而不是上面的ITU-R加权因子

编辑


得到的亮度值范围为0..255,其中0最暗,255最亮。
tinycolor
将大于128的值视为灯光。(无耻地抄袭@pau.moreno和@Alnitak的评论)

一个可能的解决方案是转换你的颜色。HSB表示色调、饱和度和亮度(也称为HSV,其中V表示值)。然后您只需检查一个参数:亮度。

您可以计算:

因此,亮度是表面亮度的指示器

因此,最好选择文本是白色还是黑色

var getRGB = function(b){
    var a;
    if(b&&b.constructor==Array&&b.length==3)return b;
    if(a=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(b))return[parseInt(a[1]),parseInt(a[2]),parseInt(a[3])];
    if(a=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(b))return[parseFloat(a[1])*2.55,parseFloat(a[2])*2.55,parseFloat(a[3])*2.55];
    if(a=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(b))return[parseInt(a[1],16),parseInt(a[2],16),parseInt(a[3],
16)];
    if(a=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(b))return[parseInt(a[1]+a[1],16),parseInt(a[2]+a[2],16),parseInt(a[3]+a[3],16)];
    return (typeof (colors) != "undefined")?colors[jQuery.trim(b).toLowerCase()]:null
};

var luminance_get = function(color) {
    var rgb = getRGB(color);
    if (!rgb) return null;
        return 0.2126 * rgb[0] + 0.7152 * rgb[1] + 0.0722 * rgb[2];
}
上面的方法允许您以不同的格式传递颜色,但算法基本上只是在
luminance\u get


当我使用它时,如果亮度大于180,我将颜色设置为黑色,否则设置为白色。

亮度和亮度之间有一个重要的区别。亮度,在一天结束时,是一个衡量有多少能量通过某个区域的度量,完全忽略了我们的感知系统是如何感知能量的。另一方面,亮度是我们如何感知能量的一种度量,它考虑了亮度和我们的感知系统之间的关系。(令人困惑的是,有一个术语叫做相对亮度,它似乎是亮度术语的同义词。这让我很困惑)

准确地说,您正在寻找其他人建议的“亮度”或“值”或“相对亮度”。你可以用几种不同的方法来计算(这就是人类!)

  • 取R、G和B的最大值
  • 从R、G和B中取最大值和最小值的平均值
  • 取三者的平均值
  • 使用此处其他人建议的加权平均值
  • 库(您已经提到)提供了几个用于检查和操作颜色的函数,其中包括:

    • 返回颜色的感知亮度,从0到255,由定义

    • 返回一个布尔值,指示颜色的感知亮度是否为灯光

      tinycolor("#fff").isLight(); // true
      tinycolor("#000").isLight(); // false
      
    • 返回一个布尔值,指示颜色的感知亮度是否为暗

      tinycolor("#fff").isDark(); // false
      tinycolor("#000").isDark(); // true
      
    • 返回颜色的感知亮度,从0到1,由定义


      • 我意识到这段对话已经进行了几年,但它仍然是相关的。我想补充一点,我的团队在Java(SWT)中也遇到了同样的问题,并且发现这一点更加准确:

        private Color getFontColor(RGB bgColor) {
            Color COLOR_BLACK = new Color(Display.getDefault(), 0, 0, 0);
            Color COLOR_WHITE = new Color(Display.getDefault(), 255, 255, 255);
        
            double luminance = Math.sqrt(0.241 
               * Math.pow(bgColor.red, 2) + 0.691 * Math.pow(bgColor.green, 2) +  0.068 
               * Math.pow(bgColor.blue, 2));
            if (luminance >= 130) {
                return COLOR_BLACK;
            } else {
                return COLOR_WHITE;
            }
        }
        
        这项工作与hex有关,例如#fefefe

        return(yiq<40);
        
        我找到了这个WoodCommerce Wordpress PHP函数()并将其转换为JavaScript。很好

        function wc_hex_is_light(color) {
            const hex = color.replace('#', '');
            const c_r = parseInt(hex.substr(0, 2), 16);
            const c_g = parseInt(hex.substr(2, 2), 16);
            const c_b = parseInt(hex.substr(4, 2), 16);
            const brightness = ((c_r * 299) + (c_g * 587) + (c_b * 114)) / 1000;
            return brightness > 155;
        }
        

        你有没有试过设置一个颜色选择器并检查值?我注意到,当R、G和B都小于70时,就会变暗。这可能不是正确的方法,但它是一种。由于您已经在使用tinyColor,请将颜色转换为,然后查看L组件。1=白色,0=black@AndreasHSL亮度不考虑人类感知。L值为0.5时,不同颜色的感知亮度会不同。@Alnitak你说得对,但TO的描述并不准确。因此,任何低于3/8的值都可能已经足够暗了。@Andreas这取决于-如果你在我的回答中查看ITU亮度值,你会发现蓝色的亮度只有绿色的1/10。有一段时间没有在javascript中看到一些好的位操作了。很酷的东西。很好的代码,但经过测试后,我建议var-luma=(r+g+b)/3;如果(luma<128){//会更有用。}@TerryLin为什么?给出的系数是标准的ITU值,考虑到绿色比红色(然后是蓝色)更明亮。由此产生的
        luma
        值范围为
        0..255
        ,其中
        0
        最暗,
        255
        最轻(三个系数相加为一)。@Gabsnake自2014年5月起,而
        isDark()
        阈值是硬编码的128AFAIK,只有维基百科页面上描述的luma计算是基于感知的模型。指出物理光能和感知亮度之间的区别很好,但我认为你把事情搞混了。你链接到的维基百科文章中有第四个要点,指出“一个更具感知相关性的替代方案是使用luma,Y′,作为亮度维度”(强调我的),然后继续给出Alnitak和Robin的答案中给出的公式。换言之,您忽略并再次推荐的方法
        private Color getFontColor(RGB bgColor) {
            Color COLOR_BLACK = new Color(Display.getDefault(), 0, 0, 0);
            Color COLOR_WHITE = new Color(Display.getDefault(), 255, 255, 255);
        
            double luminance = Math.sqrt(0.241 
               * Math.pow(bgColor.red, 2) + 0.691 * Math.pow(bgColor.green, 2) +  0.068 
               * Math.pow(bgColor.blue, 2));
            if (luminance >= 130) {
                return COLOR_BLACK;
            } else {
                return COLOR_WHITE;
            }
        }
        
        function isTooDark(hexcolor){
            var r = parseInt(hexcolor.substr(1,2),16);
            var g = parseInt(hexcolor.substr(3,2),16);
            var b = parseInt(hexcolor.substr(4,2),16);
            var yiq = ((r*299)+(g*587)+(b*114))/1000;
            // Return new color if to dark, else return the original
            return (yiq < 40) ? '#2980b9' : hexcolor;
        }
        
        return (yiq < 40) ? '#2980b9' : hexcolor;
        
        return (yiq < 40);
        
        function wc_hex_is_light(color) {
            const hex = color.replace('#', '');
            const c_r = parseInt(hex.substr(0, 2), 16);
            const c_g = parseInt(hex.substr(2, 2), 16);
            const c_b = parseInt(hex.substr(4, 2), 16);
            const brightness = ((c_r * 299) + (c_g * 587) + (c_b * 114)) / 1000;
            return brightness > 155;
        }