Cambie automáticamente el color del texto para garantizar la legibilidad


Los usuarios pueden establecer el color de fondo de un botón a través de un cuadro de texto que acepta notación hexadecimal RGB: ff00ff, ccaa22, etc. Así que necesito establecer el color del texto al contrario. No estoy seguro de la terminología (color opuesto), pero la idea es asegurar la legibilidad.

Author: Peter O., 2012-03-07

8 answers

Puede invertir el color de fondo y usarlo como color de primer plano. El siguiente algoritmo produce resultados idénticos al comando de color "Imagen > Ajustes > Invertir" en Photoshop:

function invertColor(hexTripletColor) {
    var color = hexTripletColor;
    color = color.substring(1);           // remove #
    color = parseInt(color, 16);          // convert to integer
    color = 0xFFFFFF ^ color;             // invert three bytes
    color = color.toString(16);           // convert to hex
    color = ("000000" + color).slice(-6); // pad with leading zeros
    color = "#" + color;                  // prepend #
    return color;
}
/*
 * Demonstration
 */
function randomColor() {
    var color;
    color = Math.floor(Math.random() * 0x1000000); // integer between 0x0 and 0xFFFFFF
    color = color.toString(16);                    // convert to hex
    color = ("000000" + color).slice(-6);          // pad with leading zeros
    color = "#" + color;                           // prepend #
    return color;
}
$(function() {
    $(".demolist li").each(function() {
        var c1 = randomColor();
        var c2 = invertColor(c1);
        $(this).text(c1 + " " + c2).css({
            "color": c1,
            "background-color": c2
        });
    });
});
body { font: bold medium monospace; }
.demolist { margin: 0; padding: 0; list-style-type: none; overflow: hidden; }
.demolist li { float: left; width: 5em; height: 5em; text-align: center; }
<ul class="demolist">
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
</ul>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

Tenga en cuenta que esta no es una solución a prueba de balas. Los colores que están cerca del 50% de brillo y / o saturación no producirán suficiente contraste.

Demostración en jsFiddle

 52
Author: Salman A,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-21 08:13:42

El código de Salaman es bueno, pero a veces su inversión no es lo suficientemente legible. Utilizo YCbCr y simplemente cambio la escala de grises.

function invertColor(rgb) {
    var yuv = rgb2yuv(rgb);
    var factor = 180;
    var threshold = 100;
    yuv.y = clamp(yuv.y + (yuv.y > threshold ? -factor : factor));
    return yuv2rgb(yuv);
}

Jsfiddle demo

 12
Author: woru,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-19 10:26:28

Vinculé otra pregunta a este tema en los comentarios.
Función JS para calcular el color complementario?

Como Tejasva dijo, necesita convertir RGB a HSL, complementar el tono y convertirlo de nuevo.

Implementé la respuesta vinculada como ejemplo. Por favor, vote el póster original si esto fue útil para usted, porque proporcionaron la solución de hecho.

Muestra
http://jsfiddle.net/pLZ89/2 /

 5
Author: Smamatti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:54:31

Tuve el mismo problema una vez, y recopilé información en todo el Internet también usando Salman Una respuesta, se me ocurrió esta función, es compatible con hex, rgb y rgba

var invertColor = function (color) {
            var hex   = '#';
            if(color.indexOf(hex) > -1){
                color = color.substring(1);           
                color = parseInt(color, 16);         
                color = 0xFFFFFF ^ color;            
                color = color.toString(16);           
                color = ("000000" + color).slice(-6); 
                color = "#" + color; 
            }else{
                color = Array.prototype.join.call(arguments).match(/(-?[0-9\.]+)/g);
                for (var i = 0; i < color.length; i++) {
                    color[i] = (i === 3 ? 1 : 255) - color[i];
                }
                if(color.length === 4){
                    color = "rgba("+color[0]+","+color[1]+","+color[2]+","+color[3]+")";
                }else{
                    color = "rgb("+color[0]+","+color[1]+","+color[2]+")";
                }
            }         
            return color;
        }

Pero no creo que esto sea lo que necesita, encontré algo más interesante, la función de abajo devolverá blanco o negro, decidirá bruja uno es más legible en el color dado.

var getContrastYIQ = function (color){
            var hex   = '#';
            var r,g,b;
            if(color.indexOf(hex) > -1){
                r = parseInt(color.substr(0,2),16);
                g = parseInt(color.substr(2,2),16);
                b = parseInt(color.substr(4,2),16);
            }else{
                color = color.match(/\d+/g);
                r = color[0];
                g = color[1];
                b = color[2];
            }

            var yiq = ((r*299)+(g*587)+(b*114))/1000;
            return (yiq >= 128) ? 'black' : 'white';
        }

No tomo crédito por nada de esto, solo me inspiré y modificé a mis necesidades.

Fuentes: Función YIQ explicada

 3
Author: ZetCoby,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-26 08:37:52

Un poco tarde para la fiesta, pero IMO todo el texto debe ser claro u oscuro. El texto coloreado es para enlaces.

Aquí hay una función coffeescript que he escrito para decidir cuál usar:

is_light = (hex_color) ->
  c = hex_color.replace(/^#/,'')
  sum = parseInt(c[0]+c[1], 16)
  sum += parseInt(c[2]+c[3], 16)
  sum += parseInt(c[4]+c[5], 16)  
  log "sum is #{sum}"
  sum > 382.6
 2
Author: Kevin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-19 06:33:48

var getContrastYIQ = function(color) {
  var hex = '#';
  var r, g, b;
  if (color.indexOf(hex) > -1) {
    r = parseInt(color.substr(1, 2), 16);
    g = parseInt(color.substr(3, 2), 16);
    b = parseInt(color.substr(5, 2), 16);
  } else {
    color = color.match(/\d+/g);
    r = color[0];
    g = color[1];
    b = color[2];
  }

  var yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;
  return (yiq >= 128) ? 'black' : 'white';
}

Gracias por el post ZetCoby! Tuve que ajustar su " color.substr ("array position to account for the initial '#'; then it worked great! también podrías usar un color.replace ( ' # ' ,"); dentro del bloque if...

 2
Author: jason,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-28 02:31:41

Puedes usar este esquema simple para lograr ese objetivo. Simplemente convierta el color de RGB a forma HSV. Puedes usar este enlace . A continuación, utilice este pseudo código;

rr = (color>>16)&0xFF;
gg = (color>>8)&0xFF;
bb = color & 0xFF;

someBrightColor = 0xFFFFFF;
someDarkColor = 0x000000;

hsvColor = rgbToHsv( rr, gg, bb );
//
//hsv is array: [h,s,v]...all values in [0,1]
//
//color is from dark range, if hsv < 0.5, so we need bright color to draw text, because    in dark color bright color 'will be more visible'.  
if( hsvColor[2] <= 0.5 )
  textColor = someBrightColor ;
//this is opposite case , when in more bright color, the dark color 'will be more visible'
else
  textColor = someDarkColor ;

También podría dividir el rango [0,1] en más partes. Y en lugar de definir 2 colores (someBrightColor,someDarkColor) , defina más colores. Mi método sugerido es 'qué tan brillante es el color de fondo, el color del texto debe ser oscuro, y viceversa'.

 1
Author: Engineer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-07 12:08:06

Aquí hay una forma muy pequeña de complementar el valor hexadecimal //valor hexadecimal como "aa00cc"

function complementHex(hexValue){
    var reqHex = "";
    for(var i=0;i<6;i++){
        reqHex = reqHex + (15-parseInt(hexValue[i],16)).toString(16);
    }
    return reqHex;
}
 1
Author: Tejasva Dhyani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-07 12:27:16