给定一个系统(例如一个网站),允许用户自定义某些部分的背景色,但不允许自定义字体颜色(以保持选项的数量最小化),是否有一种方法可以通过编程来确定“浅色”或“深色”字体颜色是必要的?
我相信有一些算法,但我对颜色、光度等了解不够,无法自己找出答案。
给定一个系统(例如一个网站),允许用户自定义某些部分的背景色,但不允许自定义字体颜色(以保持选项的数量最小化),是否有一种方法可以通过编程来确定“浅色”或“深色”字体颜色是必要的?
我相信有一些算法,但我对颜色、光度等了解不够,无法自己找出答案。
当前回答
Javascript [ES2015]
const hexToLuma = (colour) => {
const hex = colour.replace(/#/, '');
const r = parseInt(hex.substr(0, 2), 16);
const g = parseInt(hex.substr(2, 2), 16);
const b = parseInt(hex.substr(4, 2), 16);
return [
0.299 * r,
0.587 * g,
0.114 * b
].reduce((a, b) => a + b) / 255;
};
其他回答
这是一个非常有用的答案。谢谢!
我想分享一个SCSS版本:
@function is-color-light( $color ) {
// Get the components of the specified color
$red: red( $color );
$green: green( $color );
$blue: blue( $color );
// Compute the perceptive luminance, keeping
// in mind that the human eye favors green.
$l: 1 - ( 0.299 * $red + 0.587 * $green + 0.114 * $blue ) / 255;
@return ( $l < 0.5 );
}
现在弄清楚如何使用算法来自动创建菜单链接的悬停颜色。浅标题的悬停颜色较深,反之亦然。
我也遇到过类似的问题。我必须找到一种选择对比字体颜色的好方法,以便在色度/热图上显示文本标签。它必须是通用的方法,生成的颜色必须“好看”,这意味着简单地生成互补色并不是一个好的解决方案——有时它会生成奇怪的、非常强烈的颜色,很难观察和阅读。
经过长时间的测试和尝试解决这个问题,我发现最好的解决方案是选择白色字体的“深色”,和黑色字体的“明亮”的颜色。
下面是我在c#中使用的一个函数示例:
Color ContrastColor(Color color)
{
int d = 0;
// Counting the perceptive luminance - human eye favors green color...
double luminance = (0.299 * color.R + 0.587 * color.G + 0.114 * color.B)/255;
if (luminance > 0.5)
d = 0; // bright colors - black font
else
d = 255; // dark colors - white font
return Color.FromArgb(d, d, d);
}
这种方法在许多不同的颜色尺度(彩虹,灰度,热,冰,和许多其他)下进行了测试,这是我发现的唯一“通用”方法。
编辑 改变计算a的公式为“感知亮度”-它真的看起来更好!已经在我的软件中实现了,看起来很棒。
编辑2 @WebSeed提供了这个算法的一个很好的工作示例:http://codepen.io/WebSeed/full/pvgqEq/
Swift 4示例:
extension UIColor {
var isLight: Bool {
let components = cgColor.components
let firstComponent = ((components?[0]) ?? 0) * 299
let secondComponent = ((components?[1]) ?? 0) * 587
let thirdComponent = ((components?[2]) ?? 0) * 114
let brightness = (firstComponent + secondComponent + thirdComponent) / 1000
return !(brightness < 0.6)
}
}
更新-发现0.6是一个更好的查询测试平台
颤振实现
Color contrastColor(Color color) {
if (color == Colors.transparent || color.alpha < 50) {
return Colors.black;
}
double luminance = (0.299 * color.red + 0.587 * color.green + 0.114 * color.blue) / 255;
return luminance > 0.5 ? Colors.black : Colors.white;
}
基于R版本的@Gacek的答案来获得亮度(你可以很容易地应用你自己的阈值)
# vectorized
luminance = function(col) c(c(.299, .587, .114) %*% col2rgb(col)/255)
用法:
luminance(c('black', 'white', '#236FAB', 'darkred', '#01F11F'))
# [1] 0.0000000 1.0000000 0.3730039 0.1629843 0.5698039