2009-03-11 22 views
12

En una de las páginas en las que estamos trabajando actualmente, los usuarios pueden cambiar el fondo del texto que se muestra.Cálculo de colores contrastantes en javascript

Nos gustaría cambiar automáticamente el color de primer plano para mantener razonable contraste del texto.

También preferiríamos que la gama de colores fuera discrecional. Por ejemplo, si el fondo cambia de blanco a negro en 255 incrementos, no queremos ver 255 tonos de color de primer plano. En este escenario, quizás de 2 a 4, solo para mantener el contraste razonable.

¿Alguna interfaz de usuario/especialistas en diseño/color/pintores que ofrezcan la fórmula?

Respuesta

11

En términos de legibilidad, desea utilizar texto en blanco y negro en cualquier contexto que sea. Así que convierta RGB a HSV, y simplemente verifique si V es < 0.5. Si es así, blanco, si no, negro.

Pruebe primero y vea si le resulta atractivo.

Si no lo hace, es probable que desee que el blanco y el negro no sean tan claros cuando el fondo es demasiado brillante o demasiado oscuro. Para tonificar esto abajo, mantener el mismo tono y saturación, y utilizar estos valores para el brillo:

background V foreground V 
0.0-0.25  0.75 
0.25-0.5  1.0 
0.5-0.75  0.0 
0.75-1.0  0.25 

En un color medio, seguirá viendo texto negro o blanco que será muy bien legible. En un color oscuro o de color claro, verá el mismo texto de color pero al menos a 3/4 de distancia en términos de brillo y, por lo tanto, será legible. Espero que se vea bien :)

+1

Por alguna razón HSV no da el efecto deseado. HSL, por otro lado, con la excepción de algunos colores saturados, incluso en b/n puro (con un ligero sesgo hacia el negro) hace el trabajo bastante bien. – georged

+0

OK, quizás HSL es lo que realmente quise decir :) No estoy totalmente seguro. –

1

Es probable que desee cambiar el tono, pero no la saturación o el valor.

Por lo tanto, convierta su valor RGB en HSV, agregue 180 grados a H (módulo de 360 ​​grados por supuesto) y conviértalo nuevamente a RGB.

Conversion forumlas are here.

+2

Ugh, esa es una idea terrible. La tonalidad cambiante te da un desorden fangoso en el mejor de los casos (marrón café + azul oscuro) y un dolor de cabeza cegador en el peor (rojo + verde).Un curso mucho más seguro está cambiando el valor. –

0

Es un poco complicado de implementar debido a la forma en que javascript trata los valores decimales. Para este propósito, he encontrado que es mucho mejor dejar que el fondo cambie de color, pero el texto simplemente cambia entre blanco y negro. Si usa colores contrastantes, muchas combinaciones serán muy difíciles de soportar. También tenga en cuenta que algunas personas son daltónicas, por lo que no es una muy buena idea desde la perspectiva de la accesibilidad.

6

Pruebe this example, que simplemente lo establece en negro o blanco según el promedio de los valores de r, g y b. ¡También es bueno para probar! Sustituya un algoritmo mejor allí si encuentra casos que no funcionan muy bien.

<html> 
<head> 
<script> 
function rgbstringToTriplet(rgbstring) 
{ 
    var commadelim = rgbstring.substring(4,rgbstring.length-1); 
var strings = commadelim.split(","); 
var numeric = []; 
for(var i=0; i<3; i++) { numeric[i] = parseInt(strings[i]); } 
return numeric; 
} 

function adjustColour(someelement) 
{ 
    var rgbstring = someelement.style.backgroundColor; 
    var triplet = rgbstringToTriplet(rgbstring); 
    var newtriplet = []; 
    // black or white: 
    var total = 0; for (var i=0; i<triplet.length; i++) { total += triplet[i]; } 
    if(total > (3*256/2)) { 
    newtriplet = [0,0,0]; 
    } else { 
newtriplet = [255,255,255]; 
    } 
    var newstring = "rgb("+newtriplet.join(",")+")"; 
    someelement.style.color = newstring; 
    return true; 
} 

function randomiseBackground(someelement) 
{ 
var vals = []; 
for(var i=0; i<3; i++) { vals[i]=Math.floor(Math.random()*256+1); } 
someelement.style.backgroundColor="rgb("+vals.join(",")+")"; 
return true; 
} 
</script> 
</head> 
<body onload="adjustColour(document.getElementById('mypara'));"> 
<p id="mypara" style="background-color:#2287ea">Some text</p> 
<form> 
    <input type=button onclick="var elem=document.getElementById('mypara'); randomiseBackground(elem); adjustColour(elem);" value="randomise background" /> 
</form> 
</body> 
</html> 
18

Basar su decisión blanco-negro de luma funciona bastante bien para mí. La luminancia es una suma ponderada de los valores R, G y B, ajustada para la percepción humana de brillo relativo, aparentemente común en aplicaciones de video. La definición oficial de luma ha cambiado con el tiempo, con diferentes ponderaciones; mira aquí: http://en.wikipedia.org/wiki/Luma_(video). Obtuve los mejores resultados usando el Rec. Versión 709, como en el código a continuación. Un umbral blanco-negro de tal vez 165 parece bueno.

function contrastingColor(color) 
{ 
    return (luma(color) >= 165) ? '000' : 'fff'; 
} 
function luma(color) // color can be a hx string or an array of RGB values 0-255 
{ 
    var rgb = (typeof color === 'string') ? hexToRGBArray(color) : color; 
    return (0.2126 * rgb[0]) + (0.7152 * rgb[1]) + (0.0722 * rgb[2]); // SMPTE C, Rec. 709 weightings 
} 
function hexToRGBArray(color) 
{ 
    if (color.length === 3) 
     color = color.charAt(0) + color.charAt(0) + color.charAt(1) + color.charAt(1) + color.charAt(2) + color.charAt(2); 
    else if (color.length !== 6) 
     throw('Invalid hex color: ' + color); 
    var rgb = []; 
    for (var i = 0; i <= 2; i++) 
     rgb[i] = parseInt(color.substr(i * 2, 2), 16); 
    return rgb; 
}