在我们当前正在开发的页面之一上,用户可以更改显示文本的背景。
我们希望自动更改前景色以保持文本的合理的对比度。
我们还希望颜色范围是任意的。例如,如果背景以 255 个增量从白色变为黑色,我们不希望看到 255 种色调的前景色。在这种情况下,可能是 2 到 4 个,只是为了保持合理的对比度。
有任何 UI/设计/色彩专家/画家可以制定公式吗?
根据亮度做出黑白决定对我来说效果很好。亮度是 R、G 和 B 值的加权和,根据人类对相对亮度的感知进行调整,这在视频应用中显然很常见。亮度的官方定义随着时间的推移而发生变化,具有不同的权重;请参阅此处:http://en.wikipedia.org/wiki/Luma_(video)。我使用 Rec 得到了最好的结果。 709版本,如下面的代码。黑白阈值大约为 165 似乎不错。
function contrastingColor(color)
{
return (luma(color) >= 165) ? '000' : 'fff';
}
function luma(color) // color can be a hx string or an array of RGB values 0-255
{
var rgb = (typeof color === 'string') ? hexToRGBArray(color) : color;
return (0.2126 * rgb[0]) + (0.7152 * rgb[1]) + (0.0722 * rgb[2]); // SMPTE C, Rec. 709 weightings
}
function hexToRGBArray(color)
{
if (color.length === 3)
color = color.charAt(0) + color.charAt(0) + color.charAt(1) + color.charAt(1) + color.charAt(2) + color.charAt(2);
else if (color.length !== 6)
throw('Invalid hex color: ' + color);
var rgb = [];
for (var i = 0; i <= 2; i++)
rgb[i] = parseInt(color.substr(i * 2, 2), 16);
return rgb;
}
就纯粹的可读性而言,您希望在任何背景上使用黑白文本。所以将RGB转换为HSV,只需检查V是否为< 0.5. If so, white, if not, black.
先尝试一下,看看你是否觉得它有吸引力。
如果不这样做,那么当背景太亮或太暗时,您可能希望白色和黑色不要太鲜明。要降低此色调,请保持相同的色调和饱和度,并使用这些亮度值:
background V foreground V
0.0-0.25 0.75
0.25-0.5 1.0
0.5-0.75 0.0
0.75-1.0 0.25
在中等颜色上,您仍然会看到黑色或白色文本,这将具有良好的可读性。在深色或浅色上,您将看到相同颜色的文本,但亮度至少相差 3/4,因此仍然可读。我希望它看起来不错:)
尝试这个示例,它只是根据 r、g 和 b 值的平均值将其设置为黑色或白色。也适合测试!如果您发现效果不佳的情况,请替换更好的算法。
<html>
<head>
<script>
function rgbstringToTriplet(rgbstring)
{
var commadelim = rgbstring.substring(4,rgbstring.length-1);
var strings = commadelim.split(",");
var numeric = [];
for(var i=0; i<3; i++) { numeric[i] = parseInt(strings[i]); }
return numeric;
}
function adjustColour(someelement)
{
var rgbstring = someelement.style.backgroundColor;
var triplet = rgbstringToTriplet(rgbstring);
var newtriplet = [];
// black or white:
var total = 0; for (var i=0; i<triplet.length; i++) { total += triplet[i]; }
if(total > (3*256/2)) {
newtriplet = [0,0,0];
} else {
newtriplet = [255,255,255];
}
var newstring = "rgb("+newtriplet.join(",")+")";
someelement.style.color = newstring;
return true;
}
function randomiseBackground(someelement)
{
var vals = [];
for(var i=0; i<3; i++) { vals[i]=Math.floor(Math.random()*256+1); }
someelement.style.backgroundColor="rgb("+vals.join(",")+")";
return true;
}
</script>
</head>
<body onload="adjustColour(document.getElementById('mypara'));">
<p id="mypara" style="background-color:#2287ea">Some text</p>
<form>
<input type=button onclick="var elem=document.getElementById('mypara'); randomiseBackground(elem); adjustColour(elem);" value="randomise background" />
</form>
</body>
</html>
如果你使用的是d3.js,你可以用
做一些判断(简单但可能并不完美)d3.hsl(d3.color("black")).l > 0.5 ? "#000" : "fff"
或
参见示例2getLuma(r, g, b, fmt) > 165 ? "#000" : "#fff"
<script src="https://d3js.org/d3.v7.min.js"></script>
<script>
const bgColorList = ["black", "purple", "#cc1515", "green", "blue", "red", "yellow", "white"]
window.onload = () => {
d3.select("body").append("section")
.selectAll("div")
.data(bgColorList)
.enter().append("div")
.text((bgColor, idx, arr) => {
const div = arr[idx]
const {h, l} = d3.hsl(d3.color(bgColor))
const foreColor = l > 0.5 ? "#000" : "#fff"
div.outerHTML = `<div style="width:100px;height:50px;
background-color: ${bgColor};
color:${foreColor}
">Hello world</div>`
})
}
</script>
但是当
l
等于0.5时(例如:黄色、蓝色),就会有争议。
<script src="https://d3js.org/d3.v7.min.js"></script>
<table>
<tr>
<th>601</th>
<th>709</th>
<th>240</th>
</tr>
<tr id="output"></tr>
</table>
<script>
/**
* https://en.wikipedia.org/wiki/Luma_%28video%29
* @param {"601"|"709"|"240"|"145"} format
*/
function getLuma(r, g, b, format) {
switch (format) {
case "601":
return 0.2999 * r + 0.587 * g + 0.114 * b
case "709":
return 0.2126 * r + 0.7152 * g + 0.0722 * b
case "145":
case "240":
return 0.212 * r + 0.701 * g + 0.087 * b
}
}
const bgColorList = [...Array(100).keys()].map(t => d3.scaleSequential(d3.interpolateTurbo)(t / 100))
.concat(["black", "purple", "#cc1515", "green", "blue", "red", "white", "yellow"])
window.onload = () => {
const tdArr = []
d3.select("#output")
.selectAll("td")
.data(["601", "709", "240"])
.enter().append("td")
.text((fmt, _idx, _arr) => {
const td = _arr[_idx]
tdArr.push([td, fmt])
})
tdArr.forEach(([td, fmt]) => {
d3.select(td).append("section")
.selectAll("div")
.data(bgColorList)
.enter().append("div")
.text((bgColor, idx, arr) => {
const div = arr[idx]
const {r, g, b} = d3.color(bgColor)
const foreColor = getLuma(r, g, b, fmt) > 165 ? "#000" : "#fff"
// const coefficient = [0.2126, 0.7152, 0.0722]
// const foreColor = [r, g, b].reduce((sum, color, i) => sum + color * coefficient[i], 0) > 165 ? "#000" : "#fff"
div.outerHTML = `<div style="width:100px;height:26px;
background-color: ${bgColor};
color:${foreColor}
">Hello</div>`
})
})
}
</script>
由于 javascript 处理十进制值的方式,实现起来有点复杂。 为此,我发现让背景改变任何颜色但文本在黑色和白色之间切换要好得多。 如果你使用对比色,很多组合会很难忍受。另请注意,有些人是色盲,因此从可访问性的角度来看,这不是一个好主意。
这是我遇到的一个非常老的问题,但我不喜欢任何答案,所以我提供我的:
要获得合适的文本颜色,您可以检查背景颜色的亮度并返回文本的黑色或白色。
请参阅下面的演示代码中的函数 GetLumColor(),这是问题答案的关键。
<!DOCTYPE html><head></head>
<body onload="Test();">
<script type="text/javascript">
//--------------------------------------------------------------------------------
function RandomNum(Num){return Math.floor(Math.random()*Num);}
//--------------------------------------------------------------------------------
// NB: accepts rgb() or rgba() color values but the alpha-channel is not taken into consideration
function GetLumColor(Rgb){
Rgb=Rgb.replace(/ /g,'').replace('rgba(','').replace('rgb(','').replace(')','').split(',');
let R=Number(Rgb[0]), G=Number(Rgb[1]), B=Number(Rgb[2]), Color='black';
let Lum=((R+G+B)*100)/765; // luminance as a percentage
if(Lum<50){Color='white';} // adjust this number to suit
return Color;}
//--------------------------------------------------------------------------------
// Tests the function above
function Test(){
var S='', Bg='', Fg='';
for(let i=0; i<40; i++){
Bg='rgb('+RandomNum(256)+','+RandomNum(256)+','+RandomNum(256)+')';
Fg=GetLumColor(Bg);
S+='<div style="background:'+Bg+'; color:'+Fg+';"> Sample 123 </div>';
}
document.write(S);
}
//--------------------------------------------------------------------------------
</script></body></html>
基本用法...
some_ID.style.color = GetLumColor(some_ID.style.background);