2012-03-16 12 views
34

Dość prosta, wziąć żółty i biały:Jak programowo obliczyć współczynnik kontrastu między dwoma kolorami?

back_color = {r:255,g:255,b:255}; //white 
text_color = {r:255,g:255,b:0}; //yellow 

Co prawo fizyki na Boga Ziemi uniwersalnych stałych, sprawia, że ​​żółty tekst nie może być odczytany na białym tle niebieski tekst może jednak?

Ze względu na mój konfigurowalny widget wypróbowałem wszystkie możliwe modele kolorów, dla których znalazłem funkcje konwersji; nie można też powiedzieć, że zielony może być biały i żółty nie może, na podstawie jedynie porównań liczbowych.

Spojrzałem na Adsense (który jest tworzony przez Budda całego internetu) i zgadnijcie co zrobili, zrobili presetów i kolor obliczenia odległości komórki. Nie mogę tego zrobić. Moi użytkownicy mają prawo wybierania nawet najbardziej zapalnych i nieestetycznych kombinacji siatkówki, o ile tekst nadal można odczytać.

+0

więc użytkownicy mogą wybrać dowolne dwa kolory tak długo, jak są one czytelnie kontrastujące? – DanRedux

+0

Uważam, że jest to interesujące z technicznego punktu widzenia, ale bardziej praktyczne, jeśli użytkownicy mają "prawo" do wybierania kolorów, dlaczego obchodzi Cię nawet, czy można je odczytać? Czy to nie zależy od nich, aby to naprawić? – nnnnnn

+0

@nnnnnn Nie obchodzi mnie, jakie kolory wybierają, mogą mieszać, co chcą, ale zależy mi na tym, jak czytelny jest (c) 2012 Company Inc. –

Odpowiedz

38

Według Wikipedii, po przekształceniu na skalę szarości reprezentacji luminancji, "należy uzyskać wartości czerwieni, zieleni i niebieskiego" i wymieszać je w następnej proporcji: R: 30% G: 59% B: 11%

Dlatego bieli posiada 100% luminancji i żółty będzie miała 89%. W tym samym czasie zieleń ma zaledwie 59%. 11% jest prawie czterokrotnie niższe niż 41% różnicy!

I nawet wapno (#00ff00) nie jest dobre do czytania dużej ilości tekstów.

IMHO dla jasności dobrego kontrastu powinno różnić się co najmniej dla 50%. I ta jasność powinna być mierzona jako przekształcona na skalę szarości.

UPD: Ostatnio znalazłem comprehensive tool za to w internecie który w celu wykorzystuje formułę z w3 document wartości progowych może zostać podjęta z #1.4 Oto implementacja tej bardziej zaawansowanych rzeczy.

function luminanace(r, g, b) { 
    var a = [r, g, b].map(function (v) { 
     v /= 255; 
     return v <= 0.03928 
      ? v/12.92 
      : Math.pow((v + 0.055)/1.055, 2.4); 
    }); 
    return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722; 
} 
function contrast(rgb1, rgb2) { 
    return (luminanace(rgb1[0], rgb1[1], rgb1[2]) + 0.05) 
     /(luminanace(rgb2[0], rgb2[1], rgb2[2]) + 0.05); 
} 
contrast([255, 255, 255], [255, 255, 0]); // 1.074 for yellow 
contrast([255, 255, 255], [0, 0, 255]); // 8.592 for blue 
// minimal recommended contrast ratio is 4.5, or 3 for larger font-sizes 
+1

+1 To prawda. W prawdziwym życiu - Konwersja do skali szarości w celu sprawdzenia projektu jest koniecznością (szczególnie w przypadku logo). –

+0

Wybieram tę odpowiedź jako rozwiązanie, ponieważ jest ona najbardziej kompleksowa i nie mogę wybrać dwóch rozwiązań; ale wybrałbym odpowiedź HondaSuzukiShaolinShaorma, ponieważ zapewnia gotowy do użycia kod. –

+0

Tak, podoba mi się też jego odpowiedź =) – kirilloid

16

Istnieją różne sposoby obliczania kontrastu, lecz powszechnym sposobem jest ta formuła:

brightness = (299*R + 587*G + 114*B)/1000 

to zrobić dla obu kolorach, a następnie podjąć różnicę. To oczywiście daje znacznie większy kontrast dla niebieskiego na białym niż żółtym na białym.

0

Ostatnio natknąłem się na odpowiedź na tej stronie, a ja kod dokonać skrypt Adobe Illustrator, aby obliczyć współczynnik kontrastu jest.

Tutaj można zobaczyć wynik: http://screencast.com/t/utT481Ut

Niektóre skrót zapisami powyższego skryptu gdzie mylące dla mnie, a gdzie nie pracuje w Adobe rozszerzyć skrypt. Dlatego pomyślałem, że miło byłoby podzielić się moją poprawą/interpretacją kodu, który udostępnił kirilloid.

function luminance(r, g, b) { 
    var colorArray = [r, g, b]; 
    var colorFactor; 
    var i; 
    for (i = 0; i < colorArray.length; i++) { 
     colorFactor = colorArray[i]/255; 
     if (colorFactor <= 0.03928) { 
      colorFactor = colorFactor/12.92; 
     } else { 
      colorFactor = Math.pow(((colorFactor + 0.055)/1.055), 2.4); 
     } 
     colorArray[i] = colorFactor; 
    } 
    return (colorArray[0] * 0.2126 + colorArray[1] * 0.7152 + colorArray[2] * 0.0722) + 0.05; 
} 

I oczywiście trzeba wywołać tę funkcję

wewnątrz pętli for uzyskać wszystkie kolory z mojego obiektu ilustratora

//just a snippet here to demonstrate the notation 
var selection = app.activeDocument.selection; 
for (i = 0; i < selection.length; i++) { 
    red[i] = selection[i].fillColor.red; 
    //I left out the rest,because it would become to long 
} 

//this can then be used to calculate the contrast ratio. 
var foreGround = luminance(red[0], green[0], blue[0]); 
var background = luminance(red[1], green[1], blue[1]); 
luminanceValue = foreGround/background; 
luminanceValue = round(luminanceValue, 2); 

//for rounding the numbers I use this function: 
function round(number, decimals) { 
    return +(Math.round(number + "e+" + decimals) + "e-" + decimals); 
} 

Więcej informacji o współczynniku kontrastu: http://webaim.org/resources/contrastchecker/

0
module.exports = function colorcontrast (hex) { 
    var color = {}; 

    color.contrast = function(rgb) { 
     // check if we are receiving an element or element background-color 
     if (rgb instanceof jQuery) { 
      // get element background-color 
      rgb = rgb.css('background-color'); 
     } else if (typeof rgb !== 'string') { 
      return; 
     } 

     // Strip everything except the integers eg. "rgb(" and ")" and " " 
     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'; 
    }; 

    // Return public interface 
    return color; 

}; 
+0

To wygląda dobrze, ale dlaczego twoja metoda' colorcontrast' akceptuje argument "hex", ale ten argument nie jest używany? – ctlockey

0

Na podstawie odpowiedzi na kirilloidę:

kątowa Usługa obliczy kontrastu i luminescencji przekazując wartości hex:

.service('ColorContrast', [function() { 
var self = this; 

/** 
* Return iluminance value (base for getting the contrast) 
*/ 
self.calculateIlluminance = function(hexColor) { 
    return calculateIluminance(hexColor); 
}; 

/** 
* Calculate contrast value to white 
*/ 
self.contrastToWhite = function(hexColor){ 
    var whiteIlluminance = 1; 
    var illuminance = calculateIlluminance(hexColor); 
    return whiteIlluminance/illuminance; 
}; 

/** 
* Bool if there is enough contrast to white 
*/ 
self.isContrastOkToWhite = function(hexColor){ 
    return self.contrastToWhite(hexColor) > 4.5; 
}; 

/** 
* Convert HEX color to RGB 
*/ 
var hex2Rgb = function(hex) { 
    var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); 
    return result ? { 
     r: parseInt(result[1], 16), 
     g: parseInt(result[2], 16), 
     b: parseInt(result[3], 16) 
    } : null; 
}; 

/** 
* Calculate iluminance 
*/ 
var calculateIlluminance = function(hexColor) { 
    var rgbColor = hex2Rgb(hexColor); 
    var r = rgbColor.r, g = rgbColor.g, b = rgbColor.b; 
    var a = [r, g, b].map(function(v) { 
     v /= 255; 
     return (v <= 0.03928) ? 
      v/12.92 : 
      Math.pow(((v + 0.055)/1.055), 2.4); 
    }); 
    return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722; 
}; 

}]); 
Powiązane problemy