de color verde a rojo depende del porcentaje

84

Tengo un sistema de encuestas y quiero que las respuestas de esta encuesta sean de color. Por ejemplo: si es 10% sería rojo, si 40% sería amarillo y si 80% sería verde, así que quiero que mi código javascript use los colores rgb para hacer un color de acuerdo con el porcentaje dado.

function hexFromRGB(r, g, b) {
    var hex = [
        r.toString( 16 ),
        g.toString( 16 ),
        b.toString( 16 )
    ];
    $.each( hex, function( nr, val ) {
        if ( val.length === 1 ) {
            hex[ nr ] = "0" + val;
        }
    });
    return hex.join( "" ).toUpperCase();
}  

Ahora quiero hexadecimal del porcentaje.

soy yo
fuente

Respuestas:

87

Esto puede ser más de lo que necesita, pero esto le permite configurar cualquier mapa de color arbitrario:

var percentColors = [
    { pct: 0.0, color: { r: 0xff, g: 0x00, b: 0 } },
    { pct: 0.5, color: { r: 0xff, g: 0xff, b: 0 } },
    { pct: 1.0, color: { r: 0x00, g: 0xff, b: 0 } } ];

var getColorForPercentage = function(pct) {
    for (var i = 1; i < percentColors.length - 1; i++) {
        if (pct < percentColors[i].pct) {
            break;
        }
    }
    var lower = percentColors[i - 1];
    var upper = percentColors[i];
    var range = upper.pct - lower.pct;
    var rangePct = (pct - lower.pct) / range;
    var pctLower = 1 - rangePct;
    var pctUpper = rangePct;
    var color = {
        r: Math.floor(lower.color.r * pctLower + upper.color.r * pctUpper),
        g: Math.floor(lower.color.g * pctLower + upper.color.g * pctUpper),
        b: Math.floor(lower.color.b * pctLower + upper.color.b * pctUpper)
    };
    return 'rgb(' + [color.r, color.g, color.b].join(',') + ')';
    // or output as hex if preferred
};
Jacob
fuente
1
Wow, gracias Señor @Jacob ^ - ^ https://jsfiddle.net/JeancarloFontalvo/1sco9Lpe/3/
Jeancarlo Fontalvo
Esto es exactamente lo que necesito para un proyecto. ¡Muchas gracias @Jacob!
Savado
1
Jesús, esto es increíble
Tallboy
Muchas gracias. ¡Esto fue muy útil para un proyecto en el que estoy trabajando!
rayalois22
122

Un esquema simple que usa HSL junto con violín:

function getColor(value){
    //value from 0 to 1
    var hue=((1-value)*120).toString(10);
    return ["hsl(",hue,",100%,50%)"].join("");
}

ajusta la saturación y la luminosidad según sea necesario. y un violín .

function getColor(value) {
  //value from 0 to 1
  var hue = ((1 - value) * 120).toString(10);
  return ["hsl(", hue, ",100%,50%)"].join("");
}
var len = 20;
for (var i = 0; i <= len; i++) {
  var value = i / len;
  var d = document.createElement('div');
  d.textContent = "value=" + value;
  d.style.backgroundColor = getColor(value);
  document.body.appendChild(d);
}

jongo45
fuente
3
Entonces, es una caja negra. ¿Alguna explicación?
Saeed Neamati
6
De rojo a verde. var hue = (valor * 120) .toString (10);
Qian Chen
3
¿Cómo podría adaptar esto para incluir un valor mínimo y máximo? Por ejemplo, getColor(12,0,100)( getColor(value, min, max))?
Abogado del diablo
Elimine eso, no funciona al 100%: stackoverflow.com/questions/40110721/…
Abogado del diablo
@SaeedNeamati Establece el tono entre 0 y 120 (que representa el rojo al verde) según el valor que pase (0 a 1). Convierte el tono en una cadena ("0" a "120"), luego devuelve una cadena que codifica el color en formato hsl (tono, saturación, luminosidad), con la saturación configurada en 100% y la luminosidad en 50%.
mattsoave
38

Puede hacer esto en unas pocas líneas de código (sin incluir comentarios) sin necesidad de mapas de colores.

function hsl_col_perc(percent, start, end) {
  var a = percent / 100,
      b = (end - start) * a,
      c = b + start;

  // Return a CSS HSL string
  return 'hsl('+c+', 100%, 50%)';
}
//Change the start and end values to reflect the hue map
//Refernece : http://www.ncl.ucar.edu/Applications/Images/colormap_6_3_lg.png

/*
Quick ref:
    0 – red
    60 – yellow
    120 – green
    180 – turquoise
    240 – blue
    300 – pink
    360 – red
*/      

Ejemplo: https://jsfiddle.net/x363g1yc/634/

No se necesitan mapas de color (a menos que sea un cambio de color no lineal, que no se solicitó)

Advertencia: esto no es compatible con IE8 o inferior. (Gracias Bernhard Fürst)

Mattisdada
fuente
Usar el modelo de color HSL es genial, pero desafortunadamente no funciona en Internet Explorer 8.
Bernhard Fürst
Esto es cierto, corregiré mi respuesta
Mattisdada
¿Puedes explicar starty enden esto?
Abogado del diablo
1
No, endes la diferencia entre el color inicial y final en el código anterior. hsl_col_perc(100, 60, 120)resultará en turquesa en lugar de verde. Debe cambiar la segunda línea a b = (end-start)*a, o simplemente convertirla en una línea, ya que sería más fácil de leer.
riv
1
¡Gracias por salir en la rápida referencia de color HSL!
ohsully
13

Este método funciona bien en este caso (porcentaje de 0 a 100):

function getGreenToRed(percent){
            r = percent<50 ? 255 : Math.floor(255-(percent*2-100)*255/100);
            g = percent>50 ? 255 : Math.floor((percent*2)*255/100);
            return 'rgb('+r+','+g+',0)';
        }
zmc
fuente
6
function hexFromRGBPercent(r, g, b) {
    var hex = [
        Math.floor(r / 100 * 255).toString( 16 ),
        Math.floor(g / 100 * 255).toString( 16 ),
        Math.floor(b / 100 * 255).toString( 16 )
    ];
    $.each( hex, function( nr, val ) {
        if ( val.length === 1 ) {
            hex[ nr ] = "0" + val;
        }
    });
    return hex.join( "" ).toUpperCase();
}

El crédito es para Andrew. Fue más rápido.

Joseph Marikle
fuente
5

Sé que esta es originalmente una vieja pregunta de JavaScript, pero llegué aquí buscando una solución única de CSS , por lo que tal vez ayude a otros por igual: en realidad es bastante simple:

¡Utilice el porcentaje como valor de color HSL! De rojo a verde se extiende H de 0a 128. (Por lo que puede aumentar el porcentaje 1.2si lo desea). Ejemplo:

background-color:hsl(perc,100%,50%);

Donde perc es solo el número, sin el %signo.

Rmaxx
fuente
3

Esto es lo que se me ocurrió:

function rgbify(maxval, minval, val, moreisgood) {
    var intnsty = (val - minval) / (maxval - minval);
    var r, g;
    if (moreisgood) {
        if (intnsty > 0.5) {
            g = 255;
            r = Math.round(2 * (1 - intnsty) * 255);
        } else {
            r = 255;
            g = Math.round(2 * intnsty * 255);
        }

    } else { //lessisgood
        if (intnsty > 0.5) {
            r = 255;
            g = Math.round(2 * (1 - intnsty) * 255);
        } else {
            g = 255;
            r = Math.round(2 * intnsty * 255);
        }
    }
    return "rgb(" + r.toString() + ", " + g.toString() + ", 0)";
}

jsfiddle

La moreisgoodbandera cambia si los valores más altos deben ser rojos o verdes. maxvaly minvalson los valores de umbral para su rango. vales el valor a convertir a rgb

keithxm23
fuente
3

El cambio de reda greencolor utilizando HLS. El valor debe ser de 0 a 100, en este caso simulando porcentaje (%).

function getColorFromRedToGreenByPercentage(value) {
    const hue = Math.round(value);
    return ["hsl(", hue, ", 50%, 50%)"].join("");
}
fgfernandez0321
fuente
Muy agradable porque admite colores apagados decentes si los necesita :)
dijipiji
3

Basado en la respuesta de Jacobs, hice una barra de carga. Este es de verde a rojo, pero puedes cambiar los colores. Para aquellos interesados, aquí está mi código y el jsfiddle ( http://jsfiddle.net/rxR3x/ )

var percentColors = [
    { pct: 0, color: '#00FF00' },   { pct: 3, color: '#12FF00' },   { pct: 6, color: '#24FF00' },
    { pct: 10, color: '#47FF00' },  { pct: 13, color: '#58FF00' },  { pct: 16, color: '#6AFF00' },
    { pct: 20, color: '#7CFF00' },  { pct: 23, color: '#8DFF00' },  { pct: 26, color: '#9FFF00' },
    { pct: 30, color: '#B0FF00' },  { pct: 33, color: '#C2FF00' },  { pct: 36, color: '#D4FF00' },
    { pct: 40, color: '#E5FF00' },  { pct: 43, color: '#F7FF00' },  { pct: 46, color: '#FFF600' },
    { pct: 50, color: '#FFE400' },  { pct: 53, color: '#FFD300' },  { pct: 56, color: '#FFC100' },
    { pct: 60, color: '#FFAF00' },  { pct: 63, color: '#FF9E00' },  { pct: 66, color: '#FF8C00' },
    { pct: 70, color: '#FF7B00' },  { pct: 73, color: '#FF6900' },  { pct: 76, color: '#FF5700' },
    { pct: 80, color: '#FF4600' },  { pct: 83, color: '#FF3400' },  { pct: 86, color: '#FF2300' },
    { pct: 90, color: '#FF1100' },  { pct: 93, color: '#FF0000' },  { pct: 96, color: '#FF0000' },
    { pct: 100, color: '#FF0000' }
];
var getColorPercent = function(selector, percent, time){
    var i = 0;
    var percentInterval = setInterval(function() {
         i++;
         if(percent >= percentColors[i].pct) {
            console.log(percentColors[i].color);
            $(selector).css('background-color', percentColors[i].color);
        }
        if(percentColors[i].pct>=percent) {
            clearInterval(percentInterval);
        }
    }, time/25);
    $(selector).animate({width:(200/100)*percent}, time);
}
getColorPercent('#loadbar_storage', 100, 1500);

Aaron
fuente
2

Modifica estas dos líneas en el código de Jacob:

var lower = percentColors[i - 1];
var upper = percentColors[i];

a:

var lower = (i === 0) ?  percentColors[i] : percentColors[i - 1];
var upper = (i === 0) ? percentColors[i + 1] : percentColors[i];

si desea que funcione para los dos extremos (es decir, 0.0 y 1.0).

nerfólogo
fuente
2

Sé que esto es una especie de salto al tema, pero encontré una forma más de hacerlo.

Para hacer esto, también puede crear un lienzo dinámico de dimensión 100x1 y aplicarle degradado y luego desde la función solo necesita obtener el color de píxel de la ubicación porcentual.

Aquí está el código: Esto es global:

/* dynamic canvas */

// this should be done once in a page so out of function, makes function faster
var colorBook = $('<canvas />')[0];
colorBook.width = 101;
colorBook.height = 1;
var ctx = colorBook.getContext("2d");
var grd = ctx.createLinearGradient(0, 0, 101, 0);
grd.addColorStop(0, "rgb(255,0,0)"); //red
grd.addColorStop(0.5, "rgb(255,255,0)"); //yellow
grd.addColorStop(1, "rgb(0,255,0)"); //green    
ctx.fillStyle = grd;
ctx.fillRect(0, 0, 101, 1);

Entonces la función:

function getColor(value) {
  return 'rgba(' + ctx.getImageData(Math.round(value), 0, 1, 1).data.join() + ')';
}

Demostración: https://jsfiddle.net/asu09csj/

Zeus
fuente
1

HSL funcionará en IE8 usando jquery-ui-1.10.4.

Modifiqué la respuesta de jongo45 para aceptar ligereza en la función.

function getColor(value, lightness) {
    //value from 0 to 1
    var hue = ((value) * 120).toString(10);
    return ["hsl(", hue, ",100%,", lightness, "%)"].join("");
}
Justin Russell
fuente
1

El código de Mattisdada fue realmente útil para mí mientras hacía un gráfico para mostrar estadísticas de algunos resultados de pruebas. Lo modifiqué un poco para permitir el "recorte" del porcentaje (no estoy seguro de cuál es el término correcto) y también para trabajar en ambos sentidos a lo largo de la rueda de colores, por ejemplo, de verde (120) a rojo (0) y viceversa.

function pickColourByScale(percent, clip, saturation, start, end)
{
    var a = (percent <= clip) ? 0 : (((percent - clip) / (100 - clip))),
        b = Math.abs(end - start) * a,
        c = (end > start) ? (start + b) : (start - b);
    return 'hsl(' + c + ','+ saturation +'%,50%)';
}

Básicamente, al establecer un valor de porcentaje para recortar la escala, todo lo que esté por debajo de ese valor se coloreará como su color de inicio. También recalcula la escala de acuerdo al 100% de recorte.

Veamos un escenario de ejemplo en el que ingreso los siguientes valores:

  • por ciento: 75
  • clip: 50
  • saturación: 100 (sin importancia, lo uso para resaltar un gráfico Chart.js)
  • inicio: 0 (rojo)
  • final: 120 (verde)

    1. Verifico si el porcentaje es menor que el clip y devuelvo 0% si lo es. De lo contrario, vuelvo a calcular el porcentaje: el 75% está a la mitad entre el 50% y el 100%, por lo que obtengo el 50%. Esto me da 0.5.
    2. Entiendo la diferencia entre el principio y el final. Necesita usar Math.abs () en caso de que su valor de tono inicial sea mayor que su valor de tono final. Luego multiplico la diferencia por el resultado obtenido en el paso 1 para ver cuánto necesito compensar el valor de tono inicial.
    3. Si el valor inicial es mayor que el valor final, entonces debe moverse a lo largo de la rueda de colores en la dirección opuesta. Suma o resta del valor inicial según corresponda.

Termino con amarillo, que está a medio camino entre el rojo y el verde. Si no hubiera hecho el recálculo en el paso 1, habría terminado con un color más verdoso, lo que podría ser engañoso.

Seyren
fuente
0

Modifiqué la respuesta de zmc para dar un degradado de verde (0%) a rojo (100%).

const getGreenToRed = (percent) => {
    const r = 255 * percent/100;
    const g = 255 - (255 * percent/100);
    return 'rgb('+r+','+g+',0)';
}
Steve
fuente