【问题标题】:Automatically change text color to assure readability自动更改文本颜色以确保可读性
【发布时间】:2012-03-24 21:51:52
【问题描述】:

用户可以通过接受 RGB 十六进制表示法的文本框设置按钮的背景颜色:ff00ffccaa22 等。所以我需要将文本颜色设置为相反。不确定术语(相反的颜色),但想法是确保可读性。

【问题讨论】:

  • 这将对您有所帮助:stackoverflow.com/questions/1664140/…
  • 需要做的是把这个RGB转成HSL,补Hue(hue=hue+180mod360),再转回RGB...找转码mjijackson.com/2008/02/…跨度>
  • @smamatti && tejasva-dhyani:我正在研究这两种解决方案。看起来很有希望。谢谢!
  • 实际上是十六进制值的 15 的补码......我不知道它是否有效。

标签: javascript text colors background


【解决方案1】:

您可以反转背景颜色并将其用作前景色。以下算法产生的结果与 Photoshop 中的“图像 > 调整 > 反转”颜色命令相同:

function invertColor(hexTripletColor) {
    var color = hexTripletColor;
    color = color.substring(1);           // remove #
    color = parseInt(color, 16);          // convert to integer
    color = 0xFFFFFF ^ color;             // invert three bytes
    color = color.toString(16);           // convert to hex
    color = ("000000" + color).slice(-6); // pad with leading zeros
    color = "#" + color;                  // prepend #
    return color;
}
/*
 * Demonstration
 */
function randomColor() {
    var color;
    color = Math.floor(Math.random() * 0x1000000); // integer between 0x0 and 0xFFFFFF
    color = color.toString(16);                    // convert to hex
    color = ("000000" + color).slice(-6);          // pad with leading zeros
    color = "#" + color;                           // prepend #
    return color;
}
$(function() {
    $(".demolist li").each(function() {
        var c1 = randomColor();
        var c2 = invertColor(c1);
        $(this).text(c1 + " " + c2).css({
            "color": c1,
            "background-color": c2
        });
    });
});
body { font: bold medium monospace; }
.demolist { margin: 0; padding: 0; list-style-type: none; overflow: hidden; }
.demolist li { float: left; width: 5em; height: 5em; text-align: center; }
<ul class="demolist">
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
</ul>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

请注意,这不是万无一失的解决方案。亮度和/或饱和度接近 50% 的颜色不会产生足够的对比度。

Demo on jsFiddle

【讨论】:

  • 该死的,这是一个很好的例子!
  • 对于大多数颜色都非常有效,但 - 正如上面的注释所暗示的 - 并非适用于所有颜色。对于灰色 (#7F7F7F),它返回 (#808080),这实际上是相同的。 “关门但没有雪茄” :(
【解决方案2】:

Salaman 的代码很好,但有时他的反演不够可读。 我使用YCbCr,只是改变灰度。

function invertColor(rgb) {
    var yuv = rgb2yuv(rgb);
    var factor = 180;
    var threshold = 100;
    yuv.y = clamp(yuv.y + (yuv.y > threshold ? -factor : factor));
    return yuv2rgb(yuv);
}

jsfiddle demo

【讨论】:

  • 此算法在某些颜色上失败。例如,红色(#FF0000)失败。文字不可读
  • 好像把invertColor函数中的factor改成180,看起来会很棒!
【解决方案3】:

我在 cmets 中将另一个问题与该主题相关联。
JS function to calculate complementary colour?

正如 Tejasva 所说,您需要将 RGB 转换为 HSL,补充色调并将其转换回来。

我将链接的答案作为示例实现。如果这对您有帮助,请为原始海报投票,因为他们实际上提供了解决方案。

示例
http://jsfiddle.net/pLZ89/2/

【讨论】:

  • 这是一个示例/演示。我想任何人都应该很容易添加检查颜色是黑色还是白色。
【解决方案4】:

我曾经遇到过同样的问题,并且在互联网上收集了所有信息,也是使用 Salman A 的答案,我想出了这个功能,它支持 hex、rgb 和 rgba

var invertColor = function (color) {
            var hex   = '#';
            if(color.indexOf(hex) > -1){
                color = color.substring(1);           
                color = parseInt(color, 16);         
                color = 0xFFFFFF ^ color;            
                color = color.toString(16);           
                color = ("000000" + color).slice(-6); 
                color = "#" + color; 
            }else{
                color = Array.prototype.join.call(arguments).match(/(-?[0-9\.]+)/g);
                for (var i = 0; i < color.length; i++) {
                    color[i] = (i === 3 ? 1 : 255) - color[i];
                }
                if(color.length === 4){
                    color = "rgba("+color[0]+","+color[1]+","+color[2]+","+color[3]+")";
                }else{
                    color = "rgb("+color[0]+","+color[1]+","+color[2]+")";
                }
            }         
            return color;
        }

但我认为这不是您需要的,我发现了一些更有趣的东西,下面的函数将返回白色或黑色,它将决定女巫在给定颜色上的可读性更高。

var getContrastYIQ = function (color){
            var hex   = '#';
            var r,g,b;
            if(color.indexOf(hex) > -1){
                r = parseInt(color.substr(0,2),16);
                g = parseInt(color.substr(2,2),16);
                b = parseInt(color.substr(4,2),16);
            }else{
                color = color.match(/\d+/g);
                r = color[0];
                g = color[1];
                b = color[2];
            }

            var yiq = ((r*299)+(g*587)+(b*114))/1000;
            return (yiq >= 128) ? 'black' : 'white';
        }

我不认为这有任何功劳,我只是受到启发并根据自己的需要进行了修改。

来源:YIQ function explained

【讨论】:

    【解决方案5】:

    聚会有点晚了,但 IMO 所有的文字都应该是浅色或深色。彩色文本用于链接。

    这是我编写的用于决定使用哪个咖啡脚本函数:

    is_light = (hex_color) ->
      c = hex_color.replace(/^#/,'')
      sum = parseInt(c[0]+c[1], 16)
      sum += parseInt(c[2]+c[3], 16)
      sum += parseInt(c[4]+c[5], 16)  
      log "sum is #{sum}"
      sum > 382.6
    

    【讨论】:

    • 你是怎么想出 382.6 的? :)
    【解决方案6】:

    var getContrastYIQ = function(color) {
      var hex = '#';
      var r, g, b;
      if (color.indexOf(hex) > -1) {
        r = parseInt(color.substr(1, 2), 16);
        g = parseInt(color.substr(3, 2), 16);
        b = parseInt(color.substr(5, 2), 16);
      } else {
        color = color.match(/\d+/g);
        r = color[0];
        g = color[1];
        b = color[2];
      }
    
      var yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;
      return (yiq >= 128) ? 'black' : 'white';
    }

    感谢 ZetCoby 的帖子!必须调整你的“color.substr(”数组位置来解释最初的'#';然后它工作得很好!你也可以在 if 块中使用 color.replace('#','');...

    【讨论】:

      【解决方案7】:

      您可以使用这个简单的架构来实现该目标。只需将颜色从 RGB 转换为 HSV 形式。您可以使用此 link 。 然后使用这个伪代码;

      rr = (color>>16)&0xFF;
      gg = (color>>8)&0xFF;
      bb = color & 0xFF;
      
      someBrightColor = 0xFFFFFF;
      someDarkColor = 0x000000;
      
      hsvColor = rgbToHsv( rr, gg, bb );
      //
      //hsv is array: [h,s,v]...all values in [0,1]
      //
      //color is from dark range, if hsv < 0.5, so we need bright color to draw text, because    in dark color bright color 'will be more visible'.  
      if( hsvColor[2] <= 0.5 )
        textColor = someBrightColor ;
      //this is opposite case , when in more bright color, the dark color 'will be more visible'
      else
        textColor = someDarkColor ;
      

      您还可以将 [0,1] 范围划分为更多部分。而不是定义 2 种颜色 (someBrightColor,someDarkColor) ,而是定义更多颜色。我建议的方法是'背景颜色有多亮,文本颜色必须是暗的,反之亦然'。

      【讨论】:

      • rgbToHsv() function 接受十进制表示法 [0, 255] 不是十六进制。但是假设我能做这个翻译,我真的不明白你的伪代码。请多解释一下。谢了!
      • 很清楚。好的。我将实施所有并通知您。同时为这项努力投赞成票,THX!
      【解决方案8】:

      这是一个非常小的补充十六进制值的方法 //十六进制值,如“aa00cc”

      function complementHex(hexValue){
          var reqHex = "";
          for(var i=0;i<6;i++){
              reqHex = reqHex + (15-parseInt(hexValue[i],16)).toString(16);
          }
          return reqHex;
      }
      

      【讨论】:

      • 不幸的是,这与上面的最佳答案有相同的问题,即对大多数颜色都非常有效,但 - 正如上面的注释所暗示的 - 并非对所有颜色都适用。对于灰色 (#7F7F7F),它返回 (#808080),这实际上是相同的。 “关门但没有雪茄” :(
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-30
      • 1970-01-01
      • 2014-05-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多