web-dev-qa-db-de.com

Wie kann man die Schriftfarbe in Weiß oder Schwarz je nach Hintergrundfarbe festlegen?

Ich möchte einige Bilder wie dieses Beispiel zeigenalt text

Die Füllfarbe wird durch ein Feld in der Datenbank mit der Farbe in Hex festgelegt (z. B. ClassX -> Color: # 66FFFF) . Nun möchte ich Daten über einer Füllung mit der ausgewählten Farbe anzeigen (wie in Bild oben), aber ich muss wissen, ob die Farbe dunkel oder hell ist, also weiß ich, ob die Wörter weiß oder schwarz sein sollten. Gibt es einen Weg? tks

139
DJPB

Aufbauend auf meiner Antwort auf eine ähnliche Frage .

Sie müssen den Hex-Code in 3 Teile aufteilen, um die einzelnen Rot-, Grün- und Blau-Intensitäten zu erhalten. Jeweils zwei Ziffern des Codes repräsentieren einen Wert in hexadezimaler Schreibweise (Basis-16). Ich werde hier nicht auf die Details der Konvertierung eingehen, sie sind leicht zu finden.

Wenn Sie die Intensitäten für die einzelnen Farben festgelegt haben, können Sie die Gesamtintensität der Farbe bestimmen und den entsprechenden Text auswählen.

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

Die Schwelle von 186 basiert auf der Theorie, kann aber nach Geschmack eingestellt werden. Basierend auf den Kommentaren unterhalb kann ein Schwellenwert von 150 für Sie besser funktionieren .


Edit: Das Obige ist einfach und funktioniert einigermaßen gut und scheint hier bei StackOverflow eine gute Akzeptanz zu haben. Einer der folgenden Kommentare zeigt jedoch, dass dies unter bestimmten Umständen dazu führen kann, dass die W3C-Richtlinien nicht eingehalten werden. Hiermit leite ich eine modifizierte Form ab, die basierend auf den Richtlinien immer den höchsten Kontrast wählt. Wenn Sie nicht den W3C-Regeln entsprechen müssen, würde ich mich an die einfachere Formel halten.

Die Formel für den Kontrast in W3C Recommendations ist (L1 + 0.05) / (L2 + 0.05), wobei L1 die Luminanz der hellsten Farbe und L2 die Luminanz des dunkelsten auf einer Skala von 0,0-1,0 ist. Die Luminanz von Schwarz ist 0,0 und Weiß ist 1,0. Durch Ersetzen dieser Werte können Sie den Wert mit dem höchsten Kontrast bestimmen. Wenn der Kontrast für Schwarz größer als der Kontrast für Weiß ist, verwenden Sie Schwarz, andernfalls Weiß. Angesichts der Leuchtdichte der Farbe, die Sie als L testen, wird der Test zu:

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

Dies vereinfacht algebraisch:

if L > sqrt(1.05 * 0.05) - 0.05

Oder ungefähr:

if L > 0.179 use #000000 else use #ffffff

Das einzige, was bleibt, ist L zu berechnen. Diese Formel ist auch in den Richtlinien angegeben und sieht aus wie die Umwandlung von sRGB in lineares RGB, gefolgt von der ITU-R-Empfehlung BT.709 für die Luminanz.

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

Der Schwellenwert von 0,179 sollte nicht geändert werden, da er an die W3C-Richtlinien gebunden ist. Wenn Sie die Ergebnisse nicht für Sie finden, probieren Sie die einfachere Formel aus.

245
Mark Ransom

Ich akzeptiere diesen Code nicht, da er nicht mein ist, aber ich lasse ihn hier, damit andere ihn in der Zukunft schnell finden können:

Basierend auf der Antwort von Mark Ransoms, hier ein Code-Snippet für die einfache Version: 

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

und hier ist der Code-Ausschnitt für die erweiterte Version:

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

Um sie zu benutzen, rufen Sie einfach an:

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

Danke auch Alx und chetstone.

18
SudoPlz

Wie wäre es damit (JavaScript-Code)?

/**
 * 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';
}
15
George Kagan

Hier ist meine Lösung in Java für 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);
6
mwieczorek

Zusätzlich zu den Rechenlösungen kann auch ein neuronales KI-Netzwerk verwendet werden. Der Vorteil ist, dass Sie es an Ihren eigenen Geschmack und Ihre Bedürfnisse anpassen können (dh weißlicher Text auf hellen gesättigten Rottönen sieht gut aus und ist genauso lesbar wie Schwarz).

Hier ist eine nette Javascript-Demo, die das Konzept veranschaulicht. Sie können Ihre eigene JS-Formel auch direkt in der Demo erstellen.

https://harthur.github.io/brain/

Nachfolgend finden Sie einige Diagramme, die mir dabei geholfen haben, meine Gedanken zu fassen um das Problem . Im ersten Diagramm ist die Helligkeit konstant 128, während Farbton und Sättigung variieren. In der zweiten Tabelle ist die Sättigung konstant 255, während Farbton und Helligkeit variieren.

In the first chart, lightness is a constant 128, while hue and saturation vary:

Saturation is a constant 255, while hue and lightness vary:

4
Félix Ménard

Dies ist nur ein Beispiel, bei dem die Farbe eines SVG-Häkchens geändert wird, wenn Sie auf ein Element klicken. Die Farbe des Häkchens wird auf der Hintergrundfarbe des angeklickten Elements auf Schwarz oder Weiß gesetzt.

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
davidcondrey

Basierend auf der Antwort von @MarkRansom habe ich ein PHP Skript erstellt, das Sie hier finden können:

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
SoBiT

Mit dieser JavaScript-Funktion konvertiere ich rgb/rgba in 'white' Oder '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';
    }
}

Sie können eines dieser Formate eingeben und es wird 'black' Oder 'white' Ausgegeben.

  • rgb(255,255,255)
  • rgba(255,255,255,0.1)
  • color:rgba(255,255,255,0.1)
  • 255,255,255,0.1
2
d-_-b

Ich habe so etwas noch nie gemacht, aber was ist mit dem Schreiben einer Funktion, um die Werte jeder Farbe mit der mittleren Farbe von Hex 7F (FF/2) zu vergleichen. Wenn zwei der drei Farben größer als 7F sind, arbeiten Sie mit einer dunkleren Farbe.

1
DJ Quimby

Mark detaillierte Antwort funktioniert super. Hier ist eine Implementierung in 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';
}

Dann kann diese Funktion lum([111, 22, 255]) aufgerufen werden, um weiß oder schwarz zu werden.

1
fireant

LESS hat eine Nice contrast()-Funktion, die gut für mich funktioniert hat, siehe http://lesscss.org/functions/#color-operations-contrast

"Wählen Sie aus, welche der beiden Farben den stärksten Kontrast zu einer anderen bietet .. _. Dies ist nützlich, um sicherzustellen, dass eine Farbe vor einem Hintergrund lesbar ist, was auch für die Einhaltung der Barrierefreiheit hilfreich ist. Diese Funktion funktioniert genauso wie die Kontrastfunktion in Compass for SASS. Gemäß WCAG 2.0 werden Farben anhand ihres gamma-korrigierten Luma-Werts und nicht anhand ihrer Helligkeit verglichen. "

Beispiel:

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

Ausgabe:

p {
    a: #000000 // black
    b: #ffffff // white
    c: #dddddd
    d: #000000 // black
    e: #ffffff // white
}
0
Pedi T.

@SoBiT, ich habe mir deine Antwort angesehen, die gut aussieht, aber es gibt einen kleinen Fehler. Ihre Funktion hexToG und hextoB müssen geringfügig bearbeitet werden. Die letzte Zahl in substr ist die Länge der Zeichenfolge. In diesem Fall sollte sie "2" und nicht 4 oder 6 sein.

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
Patch

Dies ist eine schnelle Version von Mark Ransoms Antwort als Erweiterung von 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
Rydell

Versionscode für Objective-c für iOS basierend auf Marks Antwort:

- (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
simonwjw

Basierend auf verschiedenen Eingaben aus dem Link Vordergrundfarbe schwarz oder weiß abhängig vom Hintergrund festlegen und diesem Thread habe ich eine Erweiterungsklasse für Color erstellt, die die erforderlichen Kontrastfarben ergibt.

Der Code lautet wie folgt:

 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);
    }
}
0
Kasim Husaini

Wie wäre es mit allen 24-Bit-Farben zu testen?

Beachten Sie, dass die YIQ-Methode ein minimales Kontrastverhältnis von 1,9: 1 liefert, das die AA- und AAA-WCAG2.0-Tests nicht bestanden hat, wenn ein Schwellenwert von 128 angenommen wird.

Bei der W3C-Methode wird ein minimales Kontrastverhältnis von 4,58: 1 zurückgegeben, das die AA- und AAA-Tests für großen Text und den AA-Test für kleinen Text bestanden hat. Es wird den AAA-Test für kleinen Text für jede Farbe nicht bestehen.

0
Phiphou

Hier ist meine eigene Methode, mit der ich bisher keine Probleme hatte ????

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';
0

Von Hex zu Schwarz oder Weiß:

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
Dorian