根据覆盖的背景区域的亮度更改文本颜色?

Jam*_*tta 104 javascript jquery html5 background canvas

我已经考虑了一段时间了,所以现在我想知道你的意见,可能的解决方案等等.

我正在寻找一种插件或技术来改变文本的颜色或在预定义的图像/图标之间切换,具体取决于它的父母的背景图像或颜色的覆盖像素的平均亮度.

如果其背景的覆盖区域相当暗,请将文本设为白色或切换图标.

另外,如果父脚本没有定义背景颜色或-image,然后继续搜索最接近的(从父元素到它的父元素......)脚本会发现它会很棒.

您怎么看,知道这个想法?那里有类似的东西吗?脚本的例子吗?

干杯,J.

小智 158

有趣的资源:

这是W3C算法(也有JSFiddle演示):

var rgb = [255, 0, 0];

// randomly change to showcase updates
setInterval(setContrast, 1000);

function setContrast() {
  // randomly update
  rgb[0] = Math.round(Math.random() * 255);
  rgb[1] = Math.round(Math.random() * 255);
  rgb[2] = Math.round(Math.random() * 255);

  // http://www.w3.org/TR/AERT#color-contrast
  var o = Math.round(((parseInt(rgb[0]) * 299) +
                      (parseInt(rgb[1]) * 587) +
                      (parseInt(rgb[2]) * 114)) / 1000);
  var fore = (o > 125) ? 'black' : 'white';
  var back = 'rgb(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ')';
  $('#bg').css('color', fore); 
  $('#bg').css('background-color', back);
  

}
Run Code Online (Sandbox Code Playgroud)
#bg {
  width: 200px;
  height: 50px;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="bg">Text Example</div>
Run Code Online (Sandbox Code Playgroud)


cya*_*ang 48

有关计算颜色对比度的 24种方法的文章可能会引起您的兴趣.忽略第一组函数,因为它们是错误的,但YIQ公式将帮助您确定是否使用浅色或深色前景色.

获得元素(或祖先)的背景颜色后,您可以使用文章中的此函数来确定合适的前景颜色:

function getContrastYIQ(hexcolor){
    hexcolor = hexcolor.replace("#", "");
    var r = parseInt(hexcolor.substr(0,2),16);
    var g = parseInt(hexcolor.substr(2,2),16);
    var b = parseInt(hexcolor.substr(4,2),16);
    var yiq = ((r*299)+(g*587)+(b*114))/1000;
    return (yiq >= 128) ? 'black' : 'white';
}
Run Code Online (Sandbox Code Playgroud)

  • 在es6中你可以这样做:```const getContrastYIQ = hc => {const [r,g,b] = [0,2,4] .map(p => parseInt(hc.substr(p,2)) ,16)); return((r*299)+(g*587)+(b*114))/ 1000> = 128; }``` (4认同)
  • 这个很酷,我只是将 yiq 调整为 &gt;= 160,对我来说效果更好。 (3认同)

jer*_*ris 15

有趣的问题.我的直接想法是将背景的颜色反转为文本.这涉及简单地解析背景并反转其RGB值.

像这样:http://jsfiddle.net/2VTnZ/2/

var rgb = $('#test').css('backgroundColor');
var colors = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
var brightness = 1;

var r = colors[1];
var g = colors[2];
var b = colors[3];

var ir = Math.floor((255-r)*brightness);
var ig = Math.floor((255-g)*brightness);
var ib = Math.floor((255-b)*brightness);

$('#test').css('color', 'rgb('+ir+','+ig+','+ib+')');
Run Code Online (Sandbox Code Playgroud)

  • 如果背景颜色是"#808080"怎么办? (2认同)

van*_*owm 8

在 es6 中,可以使用以下一行计算十六进制 6 字符颜色字符串 (#123456) 的对比:

const contrastColor = c=>["#000","#fff"][~~([.299,.587,.114].reduce((r,v,i)=>parseInt(c.substr(i*2+1,2),16)*v+r,0)<128)];

//const color = contrastColor("#123456"); //#fff
//const color = contrastColor("#ABCDEF"); //#000
Run Code Online (Sandbox Code Playgroud)

这是分解的、可读的版本:

const contrastColor = c=>["#000","#fff"][~~([.299,.587,.114].reduce((r,v,i)=>parseInt(c.substr(i*2+1,2),16)*v+r,0)<128)];

//const color = contrastColor("#123456"); //#fff
//const color = contrastColor("#ABCDEF"); //#000
Run Code Online (Sandbox Code Playgroud)
const contrastColor = color =>
{
  const lum = [.299 /*red*/,.587 /*green*/,.114 /*blue*/]
    .reduce((result, value, index) => 
    {
      // with reduce() we can convert an array of numbers into a single number
      // result = previous result returned by this function
      // value = https://www.w3.org/TR/AERT/#color-contrast
      // index = current position index in the array
      // num = decimal number of Red, Green or Blue color
      const num = parseInt(color.substr(index * 2 + 1, 2), 16);
      return num * value + result;
    }, 0 /* result = 0 */);

  const isDark = lum < 128;
  const index = ~~isDark; // convert boolean into 0 or 1
  return ["#000","#fff"][index];
}


//demo
function setColors()
{

  for(let i = 0; i < 70; i++)
  {
    const bgColor = "#" + (~~(Math.random() * 16777216)).toString(16).padStart(6, 0);
    const color = contrastColor(bgColor);

    node = test.children[i] || document.createElement("span");
    node.style.backgroundColor = bgColor;
    node.style.color = color;
    node.textContent = bgColor;
    if (!node.parentNode)
      test.appendChild(node);
  }
}

setColors();
Run Code Online (Sandbox Code Playgroud)
#test
{
  display: flex;
  flex-wrap: wrap;
  font-family: monospace;
}
#test > *
{
  padding: 0.3em;
}
Run Code Online (Sandbox Code Playgroud)


A. *_*aby 7

通过结合答案(alex-balljeremyharris),我发现这对我来说是最好的方法:

$('.elzahaby-bg').each(function() {
  var rgb = $(this).css('backgroundColor');
  var colors = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);

  var r = colors[1];
  var g = colors[2];
  var b = colors[3];

  var o = Math.round(((parseInt(r) * 299) + (parseInt(g) * 587) + (parseInt(b) * 114)) / 1000);

  if (o > 125) {
    $(this).css('color', 'black');
  } else {
    $(this).css('color', 'white');
  }
});
Run Code Online (Sandbox Code Playgroud)
* {
  padding: 9px;
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<div class='elzahaby-bg' style='background-color:#000'>color is white</div>

<div class='elzahaby-bg' style='background-color:#fff'>color is black</div>
<div class='elzahaby-bg' style='background-color:yellow'>color is black</div>
<div class='elzahaby-bg' style='background-color:red'>color is white</div>
Run Code Online (Sandbox Code Playgroud)


Jam*_*tta 6

mix-blend-mode 绝招:

header {
  overflow: hidden;
  height: 100vh;
  background: url(https://www.w3schools.com/html/pic_mountain.jpg) 50%/cover;
}

h2 {
  color: white;
  font: 900 35vmin/50vh arial;
  text-align: center;
  mix-blend-mode: difference;
  filter: drop-shadow(0.05em 0.05em orange);
}
Run Code Online (Sandbox Code Playgroud)
<header>
  <h2 contentEditable role='textbox' aria-multiline='true' >Edit me here</h2>
</header>
Run Code Online (Sandbox Code Playgroud)

添加(2018年3月):以下是一个不错的教程,解释了所有不同类型的模式/实现:https : //css-tricks.com/css-techniques-and-effects-for-knockout-text/

  • 这不是OP所要求的。这会反转颜色,如果你有绿色背景,你会得到橙色文本。 (2认同)

cpt*_*ing 5

我发现BackgroundCheck脚本非常有用。

它检测背景的总体亮度(可以是背景图像还是彩色),并根据背景的亮度将一个类应用于所分配的文本元素(background--lightbackground--dark)。

它可以应用于静止和运动元素。

来源


Luk*_*son 5

如果您使用的是 ES6,请将十六进制转换为 RGB,然后可以使用:

const hexToRgb = hex => {
    // turn hex val to RGB
    const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
    return result
        ? {
              r: parseInt(result[1], 16),
              g: parseInt(result[2], 16),
              b: parseInt(result[3], 16)
          }
        : null
}

// calc to work out if it will match on black or white better
const setContrast = rgb =>
    (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000 > 125 ? 'black' : 'white'

const getCorrectColor = setContrast(hexToRgb(#ffffff))
Run Code Online (Sandbox Code Playgroud)