自动最大化页面上的文本对比度

An upcoming personal project faces an interesting UI challenge in which web app users will have the opportunity to change the background color of a page. At the same time, instructions on the page must remain legible, which is impossible if the text remains a fixed color.

即将到来的个人项目面临着一个有趣的UI挑战,Web应用程序用户将有机会更改页面的背景颜色。 同时,页面上的说明必须清晰易读,如果文本保持固定颜色,则这是不可能的。

The most straightforward solution to this problem is to calculate the perceived “lightness” or “darkness” of the background, and then modify the color of the text so that is opposite that value.

解决此问题的最直接方法是计算背景的感知“明暗度”或“暗度”,然后修改文本的颜色,使其该值相反

计算光度 (Calculating Luminosity)

The equation to calculate the relative luminosity of a color is well known, and fairly straightforward. If each color component (red (r), green (g) and blue (b)) is provided as a value between 0 and 1, and gamma (γ) (the compensation for the non-linear light/dark perception of human vision) is 2.2, then:

计算颜色的相对亮度的公式是众所周知的,并且相当简单。 如果每个颜色分量(红色( r ),绿色( g )和蓝色( b ))的值介于0和1之间,且伽玛 (γ)(人类视觉的非线性明暗感知补偿) )为2.2,则:

luminosity = 0.2126 * rγ + 0.7152 * gγ + 0.0722 * bγ

光度= 0.2126 * Rγ+ 0.7152 * Gγ+ 0.0722 *

The result of this calculation is a floating point value between 0 and 1, representing the relative luminosity of any color.

该计算的结果是一个介于0和1之间的浮点值,代表任何颜色的相对亮度。

获取背景色 (Getting The Background Color)

Our first challenge is getting the background color of the page. You might expect the following to work:

我们的第一个挑战是获取页面的背景色。 您可能期望以下工作:

var bgColor = document.body.style.backgroundColor;

However, the result will most likely be an empty string. document.body.style.backgroundColor will only get the inline style of the element. Instead, we need the background color of the body after all styles have been resolved. That’s getComputedStyle:

但是,结果很可能是空字符串。 document.body.style.backgroundColor将仅获取元素的内联样式。 相反,在解决所有样式之后,我们需要主体的背景色。 那就是getComputedStyle

var computedStyle = getComputedStyle(document.body, null);
var bgColor = computedStyle.backgroundColor;

Handily, in modern browsers this provides us with the background color in rgb format:

方便地,在现代浏览器中,这为我们提供了rgb格式的背景色:

rgb(10,0,255)

This color format will be returned no matter how the original style might have been applied, or even if it wasn’t defined at all. However, we need each individual red, green and blue component, not the entire rgb string. To tease out those values, I’ll create a function:

无论原始样式如何应用,甚至根本没有定义,都将返回此颜色格式。 但是,我们需要每个单独的红色,绿色和蓝色组件,而不是整个rgb字符串。 为了弄清楚这些值,我将创建一个函数:

function splitComponent(color) {
	var rgbColors=new Object();
	color = color.substring(color.indexOf('(')+1, color.indexOf(')'));
	var result = color.split(',', 3);
		return result ? { 
			r: parseFloat(result[0]/255),
			g: parseFloat(result[1]/255),
			b: parseFloat(result[2]/255)
		} : null;
}

Very simply, the function strips away the rgb prefix and parentheses, splits the numbers by looking at the commas between them, then takes each color component and divides it by 255, to yield a floating point value between 0 and 1.

很简单,该函数会去除rgb前缀和括号,通过查看它们之间的逗号来分割数字,然后取每个颜色分量并将其除以255,以产生介于0和1之间的浮点值。

设定对比 (Setting Contrast)

Returning to the main code, I’ll call on this function to judge the luminosity of the background:

返回主代码,我将调用此函数来判断背景的亮度:

var luminosity = 
	0.2126 * Math.pow(splitComponent(bgColor).r,gamma) + 
	0.7152 * Math.pow(splitComponent(bgColor).g,gamma) + 
	0.0722 * Math.pow(splitComponent(bgColor).b, gamma);

Once I have that, I can make a judgment on how to color the text above it:

了解这些内容后,就可以判断其上方的文字的颜色了:

if (luminosity < 0.5) { 
	document.body.style.color = "#fff" 
		} else { 
	document.body.style.color = "#000" 
}

现在都在一起了 (All Together Now)

The complete code for the example above, starting with the HTML:

上面示例的完整代码,以HTML开头:

<div id="ledge">
	<h1>I SHALL ALWAYS REMAIN LEDGIBLE</h1>
	<label for="bgcolor">Set the background color for this element:</label>
	<input type="color" value="#777777" id="ledgebg" name="ledgebg" oninput="changeBG(ledgebg.value)">
</div>

Initial CSS:

初始CSS:

#ledge {
	background-color: #332;
	color: #fff;
	font-family: Avenir, sans-serif;
	padding: 2rem;
	text-align: center;
}

And JavaScript:

和JavaScript:

function splitComponent(color) {
	var rgbColors=new Object();
	color = color.substring(color.indexOf('(')+1, color.indexOf(')'));
	var result = color.split(',', 3);
	return result ? { 
		r: parseFloat(result[0]/255),
		g: parseFloat(result[1]/255),
		b: parseFloat(result[2]/255) 
	} : null;
}
var gamma = 2.2,
ledge = document.getElementById("ledge");
function changeBG(colorValue){
	ledge.style.backgroundColor = colorValue;
	var computedStyle = getComputedStyle(ledge, null);
	var bgColor = computedStyle.backgroundColor;
	var luminosity = 
		0.2126 * Math.pow(splitComponent(bgColor).r,gamma) + 
		0.7152 * Math.pow(splitComponent(bgColor).g,gamma) + 
		0.0722 * Math.pow(splitComponent(bgColor).b, gamma);
	if (luminosity < 0.5) { 
		ledge.style.color = "#fff" 
	} else {
		ledge.style.color = "#000" 
	}
}

Interestingly, the color input sets the backgroundColor of an element in hex. Rather than trying to convert that value into red, green and blue components and then into floating point values, I’ve chosen to read the getComputedStyle directly after changing the background color.

有趣的是, color输入将元素的backgroundColor设置为十六进制。 与其尝试将该值转换为红色,绿色和蓝色分量,然后转换为浮点值, getComputedStyle选择更改背景颜色后直接读取getComputedStyle

替代应用 (Alternative Applications)

It might be useful to build similar functionality into a Sass mixin, if only as a method of preventing “designer creep” (i.e. the tendency for designers to choose ever-lighter low-contrast colors with thinner, finer typefaces): check out the work by Mike and Ana that extends this idea.

如果仅作为防止“设计师蠕变”的方法(即,设计师倾向于选择越来越轻的低对比色,更细,更细的字体的趋势),则在Sass mixin中构建类似功能可能是有用的:检查工作由MikeAna提出 ,扩展了这个想法。

An alternative approach would be to convert the background color into a HSL value, adding 180 to the hue component to swing the text around on the color wheel to the opposite, so-called “complementary” color. However, the combination of complementary colors is not always high contrast or aesthetically pleasing; I would tend to stick with black and white.

一种替代方法是将背景颜色转换为HSL值 ,在色相分量上增加180,以使色轮上的文本围绕相反的,即所谓的“互补色”摆动。 但是,互补色的组合并不总是具有高对比度或美观。 我倾向于坚持黑白。

Obviously this technique only works with flat background colors and text, not background images; advanced techniques will need to use <canvas> or CSS overlay blend mode for text.

显然,该技术仅适用于平坦的背景颜色和文本,而不适用于背景图像。 高级技术将需要对文本使用<canvas>CSS overlay混合模式

翻译自: https://thenewcode.com/882/Automatically-Maximize-Text-Contrast-On-A-Page

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值