我想像这个例子一样展示一些图片
填充颜色由数据库中的字段决定,用16进制表示颜色(例如:ClassX -> 颜色:#66FFFF)。 现在,我想在所选颜色的上方显示数据(如上图所示),但是我需要知道颜色是深还是浅,以便知道文字应该是白色或黑色。 有方法吗?谢谢
在我回答类似问题的帖子的基础上进行讨论。
你需要将十六进制代码分为三部分,以获取红、绿和蓝色的亮度。该代码的每2个数字代表十六进制(基数16)中的一个值。我不会在此讨论转换的详细信息,这些详细信息很容易查找。
一旦你获得了各个颜色的强度,你就可以确定颜色的整体强度并选择相应的文本。
if (red*0.299 + green*0.587 + blue*0.114) > 186 use #000000 else use #ffffff
阈值186是基于理论的,但可以根据个人喜好进行调整。根据下面的评论,对于你来说,使用150的阈值可能效果更好。
编辑:以上方法简单且效果合理,在StackOverflow社区中得到了很好的接受度。然而,下面的一条评论显示它在某些情况下会导致不符合W3C准则的情况。这里我提出了修改后的公式,该公式始终基于准则选择最高对比度。如果您不需要符合W3C规则,那么我建议您坚持使用上述更简单的公式。有关此问题的有趣讨论,请参见对比度比例数学和相关视觉问题。
在W3C建议(WCAG 2.0)中给出了对比度的公式为:(L1 + 0.05) / (L2 + 0.05)
,其中L1
是最亮颜色的亮度,L2
是最暗颜色的亮度,取值范围为0.0-1.0。黑色的亮度为0.0,白色的亮度为1.0,因此将这些值代入该公式可以确定具有最高对比度的颜色。如果黑色的对比度大于白色,则使用黑色,否则使用白色。给定您正在测试的颜色的亮度为L
,测试如下:
if (L + 0.05) / (0.0 + 0.05) > (1.0 + 0.05) / (L + 0.05) use #000000 else use #ffffff
这可以简化为代数式:
if L > sqrt(1.05 * 0.05) - 0.05
或者近似地说:
if L > 0.179 use #000000 else use #ffffff
唯一剩下的任务就是计算L
。该公式也在指南中给出,看起来需要将sRGB转换为线性RGB,然后按照ITU-R建议BT.709的亮度进行转换。for each c in r,g,b:
c = c / 255.0
if c <= 0.04045 then c = c/12.92 else c = ((c+0.055)/1.055) ^ 2.4
L = 0.2126 * r + 0.7152 * g + 0.0722 * b
0.179的阈值不应该改变,因为它与W3C指南有关。如果你发现结果不符合你的要求,尝试使用上述更简单的公式。
#D6B508
一个值为171,因此得到白色对比度。然而,对比度应该是黑色(在这里确认:http://webaim.org/resources/contrastchecker/)。 - McGarnagle我并不是这段代码的作者,所以我不会为此负责。但是我将它留在这里,方便其他人在未来快速查找:
根据Mark Ransoms的回答,以下是一个简单版本的代码片段:
function pickTextColorBasedOnBgColorSimple(bgColor, lightColor, darkColor) {
var color = (bgColor.charAt(0) === '#') ? bgColor.substring(1, 7) : bgColor;
var r = parseInt(color.substring(0, 2), 16); // hexToR
var g = parseInt(color.substring(2, 4), 16); // hexToG
var b = parseInt(color.substring(4, 6), 16); // hexToB
return (((r * 0.299) + (g * 0.587) + (b * 0.114)) > 186) ?
darkColor : lightColor;
}
以下是高级版的代码片段:
function pickTextColorBasedOnBgColorAdvanced(bgColor, lightColor, darkColor) {
var color = (bgColor.charAt(0) === '#') ? bgColor.substring(1, 7) : bgColor;
var r = parseInt(color.substring(0, 2), 16); // hexToR
var g = parseInt(color.substring(2, 4), 16); // hexToG
var b = parseInt(color.substring(4, 6), 16); // hexToB
var uicolors = [r / 255, g / 255, b / 255];
var c = uicolors.map((col) => {
if (col <= 0.03928) {
return col / 12.92;
}
return Math.pow((col + 0.055) / 1.055, 2.4);
});
var L = (0.2126 * c[0]) + (0.7152 * c[1]) + (0.0722 * c[2]);
return (L > 0.179) ? darkColor : lightColor;
}
要使用它们,只需调用:
var color = '#EEACAE' // this can be any color
pickTextColorBasedOnBgColorSimple(color, '#FFFFFF', '#000000');
此外,感谢Alx
和chetstone
。
isDark(bgColor)
。然后我的用法就是'color': isDark(color)?'white':'black'
。 - diynevalalightColor
和 darkColor
并不是很合理。 - Aaron Dunigan AtLeeNaN
。 - coler-j除了算法解决方案之外,还可以使用AI神经网络。优点在于可以根据自己的口味和需求进行定制(例如,在鲜艳的红色背景上使用淡白色文本看起来不错,而且与黑色一样易读)。
这里有一个漂亮的Javascript演示,展示了这个概念。您还可以在演示中生成自己的JS公式。
https://harthur.github.io/brain/
以下是一些图表,帮助我理解这个问题。 在第一张图表中,亮度是恒定的128,而色调和饱和度变化。在第二张图表中,饱和度是恒定的255,而色调和亮度变化。
bgColor
输入未被记录。 这是格式:
var string = ' #f876a9'; var htmlHexa = string.trim(); var rgbHexa = htmlHexa.charAt(0) === '#' ? htmlHexa.substring(1, 7) : htmlHexa; var bgColor = { r: parseInt(rgbHexa.substring(0, 2), 16) / 255, g: parseInt(rgbHexa.substring(2, 4), 16) / 255, b: parseInt(rgbHexa.substring(4, 6), 16) / 255, }; var textColor = function (bgColor) { ...
- Bruno J. S. Lesieur这段 JavaScript 代码怎么样?
/**
* Get color (black/white) depending on bgColor so it would be clearly seen.
* @param bgColor
* @returns {string}
*/
getColorByBgColor(bgColor) {
if (!bgColor) { return ''; }
return (parseInt(bgColor.replace('#', ''), 16) > 0xffffff / 2) ? '#000' : '#fff';
}
function getContrastColor(R, G, B, A) {
const brightness = R * 0.299 + G * 0.587 + B * 0.114 + (1 - A) * 255;
return brightness > 186 ? "#000000" : "#FFFFFF";
}
这是我一直在使用并且迄今为止没有任何问题的方法:
function hexToRgb(hex) {
const hexCode = hex.charAt(0) === '#'
? hex.substr(1, 6)
: hex;
const hexR = parseInt(hexCode.substr(0, 2), 16);
const hexG = parseInt(hexCode.substr(2, 2), 16);
const hexB = parseInt(hexCode.substr(4, 2), 16);
// Gets the average value of the colors
const contrastRatio = (hexR + hexG + hexB) / (255 * 3);
return contrastRatio >= 0.5
? 'black'
: 'white';
}
以下是我在Android中使用Java的解决方案:
// Put this method in whichever class you deem appropriate
// static or non-static, up to you.
public static int getContrastColor(int colorIntValue) {
int red = Color.red(colorIntValue);
int green = Color.green(colorIntValue);
int blue = Color.blue(colorIntValue);
double lum = (((0.299 * red) + ((0.587 * green) + (0.114 * blue))));
return lum > 186 ? 0xFF000000 : 0xFFFFFFFF;
}
// Usage
// If Color is represented as HEX code:
String colorHex = "#484588";
int color = Color.parseColor(colorHex);
// Or if color is Integer:
int color = 0xFF484588;
// Get White (0xFFFFFFFF) or Black (0xFF000000)
int contrastColor = WhateverClass.getContrastColor(color);
extension UIColor {
// Get the rgba components in CGFloat
var rgba: (red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) {
var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0, alpha: CGFloat = 0
getRed(&red, green: &green, blue: &blue, alpha: &alpha)
return (red, green, blue, alpha)
}
/// Return the better contrasting color, white or black
func contrastColor() -> UIColor {
let rgbArray = [rgba.red, rgba.green, rgba.blue]
let luminanceArray = rgbArray.map({ value -> (CGFloat) in
if value < 0.03928 {
return (value / 12.92)
} else {
return (pow( (value + 0.55) / 1.055, 2.4) )
}
})
let luminance = 0.2126 * luminanceArray[0] +
0.7152 * luminanceArray[1] +
0.0722 * luminanceArray[2]
return luminance > 0.179 ? UIColor.black : UIColor.white
} }
根据@MarkRansom的回答,我创建了一个PHP脚本,您可以在此处找到:
function calcC($c) {
if ($c <= 0.03928) {
return $c / 12.92;
}
else {
return pow(($c + 0.055) / 1.055, 2.4);
}
}
function cutHex($h) {
return ($h[0] == "#") ? substr($h, 1, 7) : $h;
}
function hexToR($h) {
return hexdec(substr(cutHex($h), 0, 2));
}
function hexToG($h) {
return hexdec(substr(cutHex($h), 2, 2)); // Edited
}
function hexToB($h) {
return hexdec(substr(cutHex($h), 4, 2)); // Edited
}
function computeTextColor($color) {
$r = hexToR($color);
$g = hexToG($color);
$b = hexToB($color);
$uicolors = [$r / 255, $g / 255, $b / 255];
$c = array_map("calcC", $uicolors);
$l = 0.2126 * $c[0] + 0.7152 * $c[1] + 0.0722 * $c[2];
return ($l > 0.179) ? '#000000' : '#ffffff';
}
我基于@SudoPlz提出的高级函数编写了一个函数,该函数还考虑了浅色和深色颜色:
function getTextColor (bgColor, lightColor = '#FFFFFF', darkColor = '#000000') {
const getLuminance = function (hexColor) {
var color = (hexColor.charAt(0) === '#') ? hexColor.substring(1, 7) : hexColor
var r = parseInt(color.substring(0, 2), 16) // hexToR
var g = parseInt(color.substring(2, 4), 16) // hexToG
var b = parseInt(color.substring(4, 6), 16) // hexToB
var uicolors = [r / 255, g / 255, b / 255]
var c = uicolors.map(col => col <= 0.03928 ? col / 12.92 : ((col + 0.055) / 1.055) ** 2.4)
return (0.2126 * c[0]) + (0.7152 * c[1]) + (0.0722 * c[2]);
}
var L = getLuminance(bgColor)
var L1 = getLuminance(lightColor)
var L2 = getLuminance(darkColor)
return (L > Math.sqrt((L1 + 0.05) * (L2 + 0.05)) - 0.05) ? darkColor : lightColor;
}
getTextColor('#808080')
"#000000"
getTextColor('#808080', '#FFFFFF', '#800000')
"#FFFFFF"