背景色に応じて文字色を白または黒に決めるにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/3942878

  •  30-09-2019
  •  | 
  •  

質問

この例のような画像をいくつか表示したいalt text

塗りつぶしの色は、16 進数の色を持つデータベースのフィールドによって決定されます (例:ClassX -> Color:#66FFFF)。ここで、選択した色 (上の画像のように) で塗りつぶしの上にデータを表示したいのですが、色が暗いか明るいかを知る必要があるので、単語を白にするか黒くする必要があるかを知る必要があります。方法はありますか?ちくしょう

役に立ちましたか?

解決

私の上に建物 同様の質問に答えます.

個々の赤、緑、青の強度を取得するには、ヘックスコードを3つに分割する必要があります。コードの各2桁は、16進(base-16)表記の値を表します。ここでの変換の詳細は入りません。それらは簡単に調べることができます。

個々の色の強度が得られたら、色の全体的な強度を決定し、対応するテキストを選択できます。

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

186のしきい値は理論に基づいていますが、味に合わせて調整できます。 150のしきい値の下のコメントに基づいて、あなたのためにうまくいくかもしれません。


編集: 上記はシンプルで、合理的にうまく機能しており、Stackoverflowでよく受け入れているようです。ただし、以下のコメントの1つは、状況によっては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ガイドラインに関連付けられているため、変更すべきではありません。好みではない結果が見つかった場合は、上記のシンプルな式をお試しください。

他のヒント

私はこのコードが私のものではないので、私はこのコードを信用していませんが、私は他の人が将来すぐに見つけるためにここに残しています:

マークランサムの回答に基づいて、簡単なバージョンのコードスニペットを次に示します。

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

また、ありがとう Alxchetstone.

これ(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';
}

これが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);

算術ソリューションに加えて、AIニューラルネットワークを使用することも可能です。利点は、自分の好みとニーズに合わせて調整できることです(つまり、明るい飽和赤のオフホワイトテキストは見栄えがよく、黒と同じくらい読みやすいです)。

これは、概念を示すきちんとしたJavaScriptデモです。また、デモで独自のJSフォーミュラを生成することもできます。

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

以下は私が私の心を得るのを助けたいくつかのチャートです 問題の周り。最初のチャートでは、軽さは一定の128ですが、色相と飽和は異なります。 2番目のチャートでは、飽和は一定の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:

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

これは、要素をクリックするときに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

この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

マークの詳細な答え よく働く。 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]) 白または黒を得るために。

私はこのようなことをしたことがありませんが、各色の値をHEX 7F(FF / 2)の中央値に対してチェックする関数を書くのはどうでしょうか。 3色のうち2色が7Fを超える場合、あなたは暗い色で作業しています。

これは、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
} }

リンクからのさまざまな入力に基づいています 背景に応じて、前景色を黒または白にします そして、このスレッドでは、必要なコントラスト色を与える色の拡張クラスを作成しました。

コードは以下のとおりです。

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

@SoBiT、あなたの答えを見ていましたが、それは良さそうですが、小さな間違いがあります。関数 hexToG と hextoB は少し編集する必要があります。substr の最後の数値は文字列の長さであるため、この場合は 4 や 6 ではなく「2」にする必要があります。

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

少ないものはいいです contrast() 私にとってうまく機能した機能、参照してください http://lesscss.org/functions/#color-operations-contrast

「2つの色のどれが別の色と最大のコントラストを提供するかを選択します。これは、色が背景に対して読みやすくなることを保証するのに役立ちます。これはアクセシビリティコンプライアンスにも役立ちます。この関数は、SASSのコンパスのコントラスト関数と同じように機能します。 WCAG 2.0に従って、色は軽さではなく、ガンマ補正されたLUMA値を使用して比較されます。」

例:

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
}

ヘックスから黒または白まで:

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

Markの回答に基づくiOSのObjective-Cバージョンコード:

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

24ビットすべての色でテストするのはどうですか?

YIQメソッドは、128のしきい値を想定してAAおよびAAA WCAG2.0テストに合格しない1.9:1の最小コントラスト比を返すことに注意してください。

W3Cメソッドの場合、4.58:1の最小コントラスト比を返します。これは、大きなテキストのAAおよびAAAテストに合格し、小さなテキストのAAテストで、すべての色の小さなテキストのAAAテストに合格しません。

これは私が使用しており、これまで問題がなかった私自身の方法です 😄

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

Pythonモジュールを作成して、背景色のRGBまたは六角値に基づいて前景色を選択しました。 https://github.com/azaitsev/foreground

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top