Как определить цвет шрифта в белом или черном в зависимости от цвета фона?
Я хочу показать некоторые изображения, подобные этому примеру ![alt text]()
Цвет заливки определяется полем в базе данных с цветом в шестнадцатеричном формате (например: ClassX → Цвет: # 66FFFF).
Теперь я хочу показать данные выше заливки с выбранным цветом (например, на изображении выше), но мне нужно знать, является ли цвет темным или светлым, поэтому я знаю, должны ли слова быть белыми или черными.
Есть ли способ? ТКС
Ответы
Ответ 1
Опираясь на мой ответ на аналогичный вопрос.
Вам нужно разбить шестнадцатеричный код на 3 части, чтобы получить индивидуальные интенсивности красного, зеленого и синего. Каждые 2 цифры кода представляют значение в шестнадцатеричном (основание-16) обозначении. Я не буду вдаваться в подробности конверсии здесь, их легко найти.
Когда у вас есть интенсивность для отдельных цветов, вы можете определить общую интенсивность цвета и выбрать соответствующий текст.
if (red*0.299 + green*0.587 + blue*0.114) > 186 use #000000 else use #ffffff
Порог 186 основан на теории, но может быть скорректирован по вкусу. Исходя из комментариев ниже порога 150 может работать лучше для вас.
Редактировать: Вышеуказанное просто и работает достаточно хорошо, и, кажется, здесь, в Кару, это хорошо воспринимается. Тем не менее, один из комментариев ниже показывает, что в некоторых случаях это может привести к несоблюдению рекомендаций W3C. При этом я получаю модифицированную форму, которая всегда выбирает самый высокий контраст на основе руководящих принципов. Если вам не нужно соответствовать правилам W3C, я бы придерживался более простой формулы, приведенной выше.
Формула, приведенная для контраста в Рекомендациях W3C, представляет собой (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, за которым следует рекомендация МСЭ-R BT.709 для яркости.
for each c in r,g,b:
c = c / 255.0
if c <= 0.03928 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. Если вы находите результаты не по вкусу, попробуйте более простую формулу выше.
Ответ 2
Я не беру на себя ответственность за этот код, поскольку он не мой, но я оставляю его для других, чтобы быстро найти в будущем:
На основе 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
.
Ответ 3
Как насчет этого (код 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';
}
Ответ 4
Вот мое решение в Java для Android:
// 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);
Ответ 5
В дополнение к арифметическим решениям, также можно использовать нейронную сеть ИИ. Преимущество состоит в том, что вы можете адаптировать его по своему вкусу и потребностям (т.е. не совсем белый текст на ярких насыщенных красных тонах выглядит хорошо и читается так же, как черный).
Здесь аккуратная демонстрация Javascript, которая иллюстрирует концепцию. Вы также можете создать собственную формулу JS прямо в демоверсии.
https://harthur.github.io/brain/
Ниже приведены некоторые диаграммы, которые помогли мне решить проблему.
На первом графике яркость постоянна 128, а оттенок и насыщенность меняются. На втором графике насыщенность равна 255, а оттенок и яркость варьируются.
![In the first chart, lightness is a constant 128, while hue and saturation vary:]()
![Saturation is a constant 255, while hue and lightness vary:]()
Ответ 6
Основываясь на ответе @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';
}
Ответ 7
Это просто пример, который изменит цвет значка SVG при нажатии на элемент. Он установит цвет галочки на черный или белый на основе фонового цвета элемента с щелчком.
checkmarkColor: function(el) {
var self = el;
var contrast = function checkContrast(rgb) {
// @TODO check for HEX value
// Get RGB value between parenthesis, and remove any whitespace
rgb = rgb.split(/\(([^)]+)\)/)[1].replace(/ /g, '');
// map RGB values to variables
var r = parseInt(rgb.split(',')[0], 10),
g = parseInt(rgb.split(',')[1], 10),
b = parseInt(rgb.split(',')[2], 10),
a;
// if RGBA, map alpha to variable (not currently in use)
if (rgb.split(',')[3] !== null) {
a = parseInt(rgb.split(',')[3], 10);
}
// calculate contrast of color (standard grayscale algorithmic formula)
var contrast = (Math.round(r * 299) + Math.round(g * 587) + Math.round(b * 114)) / 1000;
return (contrast >= 128) ? 'black' : 'white';
};
$('#steps .step.color .color-item .icon-ui-checkmark-shadow svg').css({
'fill': contrast($(self).css('background-color'))
});
}
onClickExtColor: function(evt) {
var self = this;
self.checkmarkColor(evt.currentTarget);
}
https://gist.github.com/dcondrey/183971f17808e9277572
Ответ 8
Я использую эту функцию JavaScript для преобразования rgb
/rgba
в 'white'
или 'black'
.
function getTextColor(rgba) {
rgba = rgba.match(/\d+/g);
if ((rgba[0] * 0.299) + (rgba[1] * 0.587) + (rgba[2] * 0.114) > 186) {
return 'black';
} else {
return 'white';
}
}
Вы можете ввести любой из этих форматов и вывести 'black'
или 'white'
-
rgb(255,255,255)
-
rgba(255,255,255,0.1)
-
color:rgba(255,255,255,0.1)
-
255,255,255,0.1
Ответ 9
Марк подробный ответ отлично работает. Вот реализация в JavaScript:
function lum(rgb) {
var lrgb = [];
rgb.forEach(function(c) {
c = c / 255.0;
if (c <= 0.03928) {
c = c / 12.92;
} else {
c = Math.pow((c + 0.055) / 1.055, 2.4);
}
lrgb.push(c);
});
var lum = 0.2126 * lrgb[0] + 0.7152 * lrgb[1] + 0.0722 * lrgb[2];
return (lum > 0.179) ? '#000000' : '#ffffff';
}
Затем можно вызвать эту функцию lum([111, 22, 255])
чтобы получить белый или черный цвет.
Ответ 10
Я никогда не делал ничего подобного, но как насчет написания функции для проверки значений каждого из цветов против медиана цвета Hex 7F (FF/2). Если два из трех цветов больше 7F, вы работаете с более темным цветом.
Ответ 11
Это быстрая версия ответа Марка Рэнсома как расширение UIColor
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
} }
Ответ 12
Основываясь на различных входных данных ссылки Сделайте цвет переднего плана черным или белым в зависимости от фона и этой темы, я создал класс расширения для цвета, который дает требуемые контрастные цвета.
Код выглядит так:
public static class ColorExtension
{
public static int PerceivedBrightness(this Color c)
{
return (int)Math.Sqrt(
c.R * c.R * .299 +
c.G * c.G * .587 +
c.B * c.B * .114);
}
public static Color ContrastColor(this Color iColor, Color darkColor,Color lightColor)
{
// Counting the perceptive luminance (aka luma) - human eye favors green color...
double luma = (iColor.PerceivedBrightness() / 255);
// Return black for bright colors, white for dark colors
return luma > 0.5 ? darkColor : lightColor;
}
public static Color ContrastColor(this Color iColor) => iColor.ContrastColor(Color.Black);
public static Color ContrastColor(this Color iColor, Color darkColor) => iColor.ContrastColor(darkColor, Color.White);
// Converts a given Color to gray
public static Color ToGray(this Color input)
{
int g = (int)(input.R * .299) + (int)(input.G * .587) + (int)(input.B * .114);
return Color.FromArgb(input.A, g, g, g);
}
}
Ответ 13
@SoBiT, я смотрел на ваш ответ, который выглядит хорошо, но в нем есть небольшая ошибка. Ваша функция hexToG и hextoB нуждаются в незначительном редактировании. Последнее число в substr - это длина строки, поэтому в этом случае его должно быть "2", а не 4 или 6.
function hexToR($h) {
return hexdec(substr(cutHex($h), 0, 2));
}
function hexToG($h) {
return hexdec(substr(cutHex($h), 2, 2));
}
function hexToB($h) {
return hexdec(substr(cutHex($h), 4, 2));
}
Ответ 14
LESS имеет приятную функцию contrast()
, которая хорошо работала для меня, см. http://lesscss.org/functions/#color-operations-contrast
"Выберите, какой из двух цветов обеспечивает наибольший контраст с другим.
Это полезно для обеспечения того, чтобы цвет был читаемым на фоне, что также полезно для соответствия доступности. Эта функция работает так же, как функция контраста в компасе для SASS. В соответствии с WCAG 2.0 цвета сравниваются с использованием их гамма-коррекции яркости, а не их легкости.
Пример:
p {
a: contrast(#bbbbbb);
b: contrast(#222222, #101010);
c: contrast(#222222, #101010, #dddddd);
d: contrast(hsl(90, 100%, 50%), #000000, #ffffff, 30%);
e: contrast(hsl(90, 100%, 50%), #000000, #ffffff, 80%);
}
Вывод:
p {
a: #000000 // black
b: #ffffff // white
c: #dddddd
d: #000000 // black
e: #ffffff // white
}
Ответ 15
От шестнадцатеричного до черного или белого:
function hexToRgb(hex) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result
? [
parseInt(result[1], 16),
parseInt(result[2], 16),
parseInt(result[3], 16)
]
: [0, 0, 0];
}
function lum(hex) {
var rgb = hexToRgb(hex)
var lrgb = [];
rgb.forEach(function(c) {
c = c / 255.0;
if (c <= 0.03928) {
c = c / 12.92;
} else {
c = Math.pow((c + 0.055) / 1.055, 2.4);
}
lrgb.push(c);
});
var lum = 0.2126 * lrgb[0] + 0.7152 * lrgb[1] + 0.0722 * lrgb[2];
return lum > 0.179 ? "#000000" : "#ffffff";
}
Ответ 16
Код версии Objective-c для iOS, основанный на ответе Марка:
- (UIColor *)contrastForegroundColor {
CGFloat red = 0, green = 0, blue = 0, alpha = 0;
[self getRed:&red green:&green blue:&blue alpha:&alpha];
NSArray<NSNumber *> *rgbArray = @[@(red), @(green), @(blue)];
NSMutableArray<NSNumber *> *parsedRGBArray = [NSMutableArray arrayWithCapacity:rgbArray.count];
for (NSNumber *item in rgbArray) {
if (item.doubleValue <= 0.03928) {
[parsedRGBArray addObject:@(item.doubleValue / 12.92)];
} else {
double newValue = pow((item.doubleValue + 0.055) / 1.055, 2.4);
[parsedRGBArray addObject:@(newValue)];
}
}
double luminance = 0.2126 * parsedRGBArray[0].doubleValue + 0.7152 * parsedRGBArray[1].doubleValue + 0.0722 * parsedRGBArray[2].doubleValue;
return luminance > 0.179 ? UIColor.blackColor : UIColor.whiteColor;
}
Ответ 17
Как насчет тестирования всех 24-битных цветов?
Имейте в виду, что метод YIQ возвращает минимальный коэффициент контрастности 1,9: 1, который не проходит тесты AAAG и AAA WCAG2.0 при условии порогового значения 128.
Для метода W3C он вернет минимальный коэффициент контрастности 4,58: 1, который пройдет тесты AA и AAA для большого текста, и тест AA для маленького текста, он не пройдет тест AAA для маленького текста для всех цветов.
Ответ 18
Вот мой собственный метод, который я использовал и с которым у меня до сих пор не было проблем 😄
const hexCode = value.charAt(0) === '#'
? value.substr(1, 6)
: value;
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);
contrastRatio >= 0.5
? 'black'
: 'white';
Ответ 19
Я сделал модуль Python для выбора цвета переднего плана на основе значения цвета фона RGB или HEX: https://github.com/azaitsev/foreground
Ответ 20
Если вы, как и я, искали версию RGBA, в которой учитывается альфа, то вот такая, которая действительно хорошо работает для обеспечения высокой контрастности.
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";
}