Как определить цвет шрифта в белом или черном цвете в зависимости от цвета фона? - PullRequest
161 голосов
/ 15 октября 2010

Я хочу показать некоторые изображения, подобные этому примеру alt text

Цвет заливки определяется полем в базе данных с цветом в шестнадцатеричном формате (например, ClassX -> Color: # 66FFFF).Теперь я хочу показать данные над заливкой с выбранным цветом (как на картинке выше), но мне нужно знать, является ли цвет темным или светлым, поэтому я знаю, должны ли слова быть белыми или черными.Есть ли способ?ТКС

Ответы [ 17 ]

267 голосов
/ 15 октября 2010

Опираясь на мой ответ на аналогичный вопрос .

Вам нужно разбить шестнадцатеричный код на 3 части, чтобы получить индивидуальные интенсивности красного, зеленого и синего.Каждые 2 цифры кода представляют значение в шестнадцатеричном (основание-16) обозначении.Я не буду вдаваться в детали преобразования, здесь их легко найти.

Как только у вас есть интенсивности для отдельных цветов, вы можете определить общую интенсивность цвета и выбрать соответствующийтекст.

if (red*0.299 + green*0.587 + blue*0.114) > 186 use #000000 else use #ffffff

Порог 186 основан на теории, но может быть скорректирован по вкусу.Исходя из комментариев ниже порога 150 может работать лучше для вас.


Редактировать: Вышеупомянутое просто и работает достаточно хорошо, и, кажется, здесь хорошо в StackOverflow.Тем не менее, один из комментариев ниже показывает, что в некоторых случаях это может привести к несоблюдению рекомендаций 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, за которым следует рекомендация ITU-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.Если вам не нравятся результаты, попробуйте более простую формулу, приведенную выше.

21 голосов
/ 05 января 2017

Я не беру на себя ответственность за этот код, поскольку он не мой, но я оставляю его здесь, чтобы другие могли быстро найти его в будущем:

На основе ответа Марка Рэнсомса приведен фрагмент кода для простой версии:

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.

16 голосов
/ 24 ноября 2015

Как насчет этого (код 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';
}
7 голосов
/ 28 сентября 2017

В дополнение к арифметическим решениям также можно использовать нейронную сеть ИИ. Преимущество заключается в том, что вы можете адаптировать его по своему вкусу и потребностям (т. Е. Не совсем белый текст на ярких насыщенных красных тонах выглядит хорошо и так же легко читается, как черный).

Вот аккуратная демонстрация 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:

7 голосов
/ 19 августа 2016

Вот мое решение на 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);
3 голосов
/ 03 февраля 2017

Основываясь на ответе @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';
}
2 голосов
/ 13 сентября 2016

Я использую эту функцию 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
2 голосов
/ 21 октября 2015

Это всего лишь пример, который изменит цвет галочки 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

1 голос
/ 28 августа 2018

Это быстрая версия ответа Марка Рэнсома как расширение 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
} }
1 голос
/ 26 июня 2018

Подробный ответ Марка отлично работает.Вот реализация в 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]), чтобы получить белый или черный.

...