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

IT技术 javascript jquery html css sass
2021-01-18 04:27:47

我正在寻找一种插件或技术,可以根据其父背景图像或颜色的覆盖像素的平均亮度来更改文本颜色或在预定义图像/图标之间切换。

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

此外,如果脚本能够注意到父元素是否没有定义的背景颜色或图像,然后继续搜索最近的(从父元素到其父元素......),那就太好了。

你怎么看,知道这个想法吗?已经有类似的东西了吗?例子?

6个回答

有趣的资源:

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

const rgb = [255, 0, 0];

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

function setContrast() {
  // Randomly update colours
  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
  const brightness = Math.round(((parseInt(rgb[0]) * 299) +
                      (parseInt(rgb[1]) * 587) +
                      (parseInt(rgb[2]) * 114)) / 1000);
  const textColour = (brightness > 125) ? 'black' : 'white';
  const backgroundColour = 'rgb(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ')';
  $('#bg').css('color', textColour); 
  $('#bg').css('background-color', backgroundColour);
}
#bg {
  width: 200px;
  height: 50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="bg">Text Example</div>

@bluejayke 不,还有其他方法;-)
2021-03-17 04:27:47
你只需要jquery来改变css吗?
2021-03-28 04:27:47
可以缩短为以下内容,前提是您向它传递一个对象 :::: const setContrast = rgb => (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000 > 125 ?'黑,白'
2021-04-11 04:27:47

这篇关于计算颜色对比度的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';
}
谢谢,这真的很有帮助..这取决于设置的背景颜色..但是您知道如何通过遍历每个像素(如循环)来获得图像的平均颜色吗?
2021-03-22 04:27:47
这个很酷,我只是将 yiq 调整为 >= 160,对我来说效果更好。
2021-03-31 04:27:47
我使用了这个函数并对其进行了一些扩展,以便您可以返回两种自定义颜色,而不是总是黑色和白色。请注意,如果两种颜色靠得很近,您可能仍然会遇到对比度问题,但这是返回绝对颜色的好方法jsfiddle.net/1905occv/1
2021-04-06 04:27:47
在 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; }
2021-04-07 04:27:47

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);
}
<header>
  <h2 contentEditable role='textbox' aria-multiline='true' >Edit me here</h2>
</header>

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

有趣的问题。我的直接想法是将背景颜色反转为文本。这涉及简单地解析背景并反转其 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+')');
2021-03-19 04:27:47
您可能希望通过平均反转的 R、G、B 值并将它们设置为彼此相等来降低“反转”颜色的饱和度。但是,此解决方案是从字符串中获取其基色,而不是从元素的 CSS 属性中获取。为可靠起见,该解决方案必须动态获取背景颜色,通常返回 rgb() 或 rgba() 值,但可能因浏览器而异。
2021-03-23 04:27:47
是的。为了便于解析,我只使用了一个十六进制值。我更新了小提琴以包括从 CSS 中获取元素的颜色。我更新了小提琴并包含了一种亮度控制(我对颜色数学一无所知,所以它可能不是真正的亮度)。
2021-03-25 04:27:47
@NathanMacInnes 它仍然会反转它,碰巧在频谱中间反转某些东西会导致它自己。这段代码只是反转了颜色,这有其局限性。
2021-03-29 04:27:47
如果背景颜色是#808080!?
2021-04-03 04:27:47

如果您使用的是 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))