Jak wybrać kolor czcionki w kolorze białym lub czarnym w zależności od koloru tła?

Chcę pokazać kilka zdjęć, takich jak ten przykład alt text

O kolorze wypełnienia decyduje pole w bazie danych z kolorem szesnastkowym(np.: ClassX - > Color: #66FFFF). Teraz chcę pokazać dane nad wypełnieniem z wybranym kolorem (JAK na obrazku powyżej), ale muszę wiedzieć, czy kolor jest ciemny czy jasny, więc wiem, czy słowa powinny być białe lub czarne. Jest jakiś sposób? tks

Author: DJPB, 2010-10-15

15 answers

Bazując na mojej odpowiedzi na podobne pytanie .

Musisz rozbić Kod hex na 3 części, aby uzyskać poszczególne intensywności czerwone, zielone i niebieskie. Każda 2 cyfra kodu reprezentuje wartość w zapisie szesnastkowym (baza-16). Nie będę tu wdawać się w szczegóły konwersji, łatwo je sprawdzić.

Po uzyskaniu intensywności dla poszczególnych kolorów można określić ogólną intensywność koloru i wybrać odpowiedni tekst.

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


Edit: powyższe jest proste i działa dość dobrze, i wydaje się mieć dobrą akceptację tutaj w StackOverflow. Jednak jedna z poniższych uwag pokazuje, że w pewnych okolicznościach może to prowadzić do nieprzestrzegania wytycznych W3C. Poniżej przedstawiam zmodyfikowaną formę, która zawsze wybiera najwyższy kontrast w oparciu o wytyczne.

Wzór podany dla kontrastu w zaleceniach W3C jest (L1 + 0.05) / (L2 + 0.05), Gdzie L1 jest luminancją najjaśniejszy kolor i L2 to luminancja najciemniejszego w skali 0,0-1,0. Luminancja czerni wynosi 0,0, a bieli 1,0, więc podstawianie tych wartości pozwala określić tę o najwyższym kontraście. Jeśli kontrast dla czerni jest większy niż kontrast dla bieli, użyj czerni, w przeciwnym razie użyj bieli. Z uwagi na luminancję koloru, który testujesz jako L, test staje się:

if (L + 0.05) / (0.0 + 0.05) > (1.0 + 0.05) / (L + 0.05) use #000000 else use #ffffff

To upraszcza algebraicznie do:

if L > sqrt(1.05 * 0.05) - 0.05

Lub w przybliżeniu:

if L > 0.179 use #000000 else use #ffffff

Pozostało tylko obliczyć L. Wzór ten jest również podany w wytycznych i wygląda jak konwersja z sRGB na liniową RGB, po której następuje ITU-R rekomendacja BT.709 dla luminancji.

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
 220
Author: Mark Ransom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:44

Co powiesz na to (kod 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';
}
 14
Author: George Kagan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-26 11:55:48

Nie przypisuję sobie tego kodu, ponieważ nie jest mój, ale zostawiam go tutaj, aby inni mogli go szybko znaleźć w przyszłości: {]}

Na podstawie odpowiedzi Marka Ransomsa, oto fragment kodu do prostej wersji:

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;
}

A oto fragment kodu dla wersji advanced:

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;
}

Aby ich użyć wystarczy zadzwonić:

var color = '#EEACAE' // this can be any color
pickTextColorBasedOnBgColorSimple(color, '#FFFFFF', '#000000');

Również, dzięki Alx i chetstone.

 12
Author: SudoPlz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-05 17:31:58

Oto moje rozwiązanie w Javie dla Androida:

// 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);
 6
Author: mwieczorek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-19 16:19:50

Oprócz rozwiązań arytmetycznych możliwe jest również wykorzystanie sieci neuronowej AI. Zaletą jest to, że można dostosować go do własnego gustu i potrzeb (np. prawie biały tekst na jasnych nasyconych czerwieniach wygląda dobrze i jest tak samo czytelny jak czarny).

Oto zgrabne demo Javascript, które ilustruje tę koncepcję. Możesz również wygenerować własną formułę JS bezpośrednio w demo.

Https://harthur.github.io/brain/

Poniżej kilka wykresów, które pomogły mi uzyskać mój umysł wokół problemu . Na pierwszym wykresie jasność jest stała 128, podczas gdy barwa i nasycenie różnią się. Na drugim wykresie nasycenie wynosi stałą 255, podczas gdy barwa i jasność są różne.

Na pierwszym wykresie jasność jest stała 128, podczas gdy barwa i nasycenie różnią się:

Nasycenie jest stałe 255, podczas gdy odcień i jasność różnią się:

 4
Author: Félix Ménard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-28 13:17:29

To tylko przykład, który zmieni kolor znacznika SVG po kliknięciu elementu. Spowoduje to ustawienie koloru znacznika na czarny lub biały w zależności od koloru tła klikniętego elementu.

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

 2
Author: davidcondrey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-28 20:44:21

Używam tej funkcji JavaScript do Konwersji rgb/rgba do 'white' lub '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';
    }
}

Możesz wprowadzić dowolny z tych formatów i wyświetli 'black' lub 'white'

  • rgb(255,255,255)
  • rgba(255,255,255,0.1)
  • color:rgba(255,255,255,0.1)
  • 255,255,255,0.1
 2
Author: d-_-b,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-29 16:09:55

Na podstawie odpowiedzi @MarkRansom stworzyłem skrypt PHP, który można znaleźć tutaj:

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
Author: SoBiT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-11 14:50:33

Nigdy czegoś takiego nie robiłem, ale co powiesz na napisanie funkcji sprawdzającej wartości każdego z kolorów względem mediany koloru Hex 7F (FF / 2). Jeśli dwa z trzech kolorów są większe niż 7F, to pracujesz z ciemniejszym kolorem.

 1
Author: DJ Quimby,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-15 14:03:46

Szczegółowa odpowiedź Marka działa świetnie. Oto implementacja w 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';
}

Następnie można wywołać tę funkcję lum([111, 22, 255]), Aby uzyskać biały lub czarny.

 1
Author: fireant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-26 03:02:19

@SoBiT, patrzyłem na Twoją odpowiedź, która wygląda dobrze, ale jest w niej mały błąd. Twoja funkcja hexToG i hextoB wymagają drobnej edycji. Ostatnia liczba w substr jest długością ciągu, a więc w tym przypadku powinna być "2", a nie 4 lub 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));
}
 0
Author: Patch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-25 15:54:39

LESS ma ładną contrast() funkcję, która mi dobrze działała, Zobacz http://lesscss.org/functions/#color-operations-contrast

"Wybierz, który z dwóch kolorów zapewnia największy kontrast z innym. Jest to przydatne do zapewnienia, że kolor jest czytelny na tle, co jest również przydatne do zapewnienia zgodności z dostępnością. Funkcja ta działa tak samo jak funkcja kontrastu w kompasie dla SASS. Zgodnie z WCAG 2.0 kolory porównywane są za pomocą ich wartość luma z korekcją gamma, a nie ich lekkość."

Przykład:

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%);
}

Wyjście:

p {
    a: #000000 // black
    b: #ffffff // white
    c: #dddddd
    d: #000000 // black
    e: #ffffff // white
}
 0
Author: Pedi T.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-19 16:02:37

Od hex do black or white:

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";
}
 0
Author: Dorian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-28 13:44:56

Objective-Kod wersji c dla iOS na podstawie odpowiedzi Marka:

- (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;
}
 0
Author: simonwjw,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-29 01:02:05

Jest to szybka wersja odpowiedzi Marka Ransoma jako rozszerzenie 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
} }
 0
Author: Rydell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-28 15:28:08