Pregunta

¿Cuál es la forma más fácil de convertir un porcentaje a un color que varía de verde (100%) a rojo (0%), con amarillo para 50%?

Estoy usando RGB de 32 bits, por lo que cada componente es un número entero entre 0 y 255. Estoy haciendo esto en C #, pero supongo que para un problema como este, el idioma realmente no importa mucho.

Según las respuestas de Marius y Andy, estoy usando la siguiente solución:

double red = (percent < 50) ? 255 : 256 - (percent - 50) * 5.12;
double green = (percent > 50) ? 255 : percent * 5.12;
var color = Color.FromArgb(255, (byte)red, (byte)green, 0);

Funciona a la perfección: solo el ajuste que tuve que hacer con la solución de Marius fue usar 256, como (255 - (porcentaje - 50) * 5.12 rendimiento -1 cuando el 100%, resultando en amarillo por alguna razón en Silverlight (-1, 255, 0) - > Amarillo ...

¿Fue útil?

Solución

Hice esta función en JavaScript. Devuelve el color es una cadena css. Toma el porcentaje como variable, con un rango de 0 a 100. El algoritmo se puede hacer en cualquier idioma:

function setColor(p){
    var red = p<50 ? 255 : Math.round(256 - (p-50)*5.12);
    var green = p>50 ? 255 : Math.round((p)*5.12);
    return "rgb(" + red + "," + green + ",0)";
}

Otros consejos

Lo que probablemente desee hacer es asignar su 0% a 100% algunos puntos en un espacio de color HSV o HSL. Desde allí puede interpolar colores (y el amarillo está entre rojo y verde :) y conviértalos a RGB . Eso te dará un buen gradiente entre los dos.

Suponiendo que utilizará el color como indicador de estado y desde una perspectiva de interfaz de usuario, sin embargo, probablemente no sea una buena idea, ya que somos muy malos al ver pequeños cambios en el color. Por lo tanto, dividir el valor en, por ejemplo, tres a siete cubos le daría diferencias más notables cuando cambien las cosas, a costa de cierta precisión (lo que probablemente no podría apreciar de todos modos).

Dejando de lado todas las matemáticas, al final recomendaría una tabla de consulta con los siguientes colores, siendo v el valor de entrada:

#e7241d for v <= 12%
#ef832c for v > 12% and v <= 36%
#fffd46 for v > 36% and v <= 60%
#9cfa40 for v > 60% and v <= 84%
#60f83d for v > 84%

Estos se han convertido de forma muy ingenua a partir de valores HSL (0.0, 1.0, 1.0), (30.0, 1.0, 1.0), (60.0, 1.0, 1.0), (90.0, 1.0, 1.0), (120.0, 1.0, 1.0 ), y es posible que desee ajustar los colores para adaptarlos a sus propósitos (a algunos no les gusta que el rojo y el verde no sean "puros").

Por favor vea:

En pseudocódigo.

  • De 0 a 50%, su valor hexadecimal sería FFxx00 donde:

    XX = ( Percentage / 50 ) * 255 converted into hex.
    
  • De 50 a 100, su valor hexadecimal sería xxFF00 donde:

    XX = ((100-Percentage) / 50) * 255 converted into hex.  
    

Espero que ayude y sea comprensible.

Esta es una buena solución limpia que mejora la respuesta actualmente aceptada de tres maneras:

  1. Elimina el número mágico (5.12), lo que hace que el código sea más fácil de seguir.
  2. No producirá el error de redondeo que le da -1 cuando el porcentaje es del 100%.
  3. Le permite personalizar los valores RGB mínimos y máximos que utiliza, para que pueda producir un rango más claro o más oscuro que el simple rgb (255, 0, 0) - rgb (0, 255, 0).

El código que se muestra es C #, pero es trivial adaptar el algoritmo a cualquier otro idioma.

private const int RGB_MAX = 255; // Reduce this for a darker range
private const int RGB_MIN = 0; // Increase this for a lighter range

private Color getColorFromPercentage(int percentage)
{
    // Work out the percentage of red and green to use (i.e. a percentage
    // of the range from RGB_MIN to RGB_MAX)
    var redPercent = Math.Min(200 - (percentage * 2), 100) / 100f;
    var greenPercent = Math.Min(percentage * 2, 100) / 100f;

    // Now convert those percentages to actual RGB values in the range
    // RGB_MIN - RGB_MAX
    var red = RGB_MIN + ((RGB_MAX - RGB_MIN) * redPercent);
    var green = RGB_MIN + ((RGB_MAX - RGB_MIN) * greenPercent);

    return Color.FromArgb(red, green, RGB_MIN);
}

Notas

Aquí hay una tabla simple que muestra algunos valores porcentuales, y las proporciones roja y verde correspondientes que queremos producir:

VALUE   GREEN    RED       RESULTING COLOUR
 100%    100%     0%       green
  75%    100%    50%       yellowy green
  50%    100%   100%       yellow
  25%     50%   100%       orange
   0%      0%   100%       red

Espero que puedas ver claramente que

  • el valor verde es 2 veces el valor porcentual (pero limitado a 100)
  • el rojo es el inverso: 2x (100 - porcentaje) (pero limitado a 100)

Entonces mi algoritmo calcula los valores de una tabla que se parece a esto ...

VALUE   GREEN    RED
 100%    200%     0%
  75%    150%    50%
  50%    100%   100%
  25%     50%   150%
   0%      0%   200%

... y luego usa Math.Min () para limitarlos al 100%.

Escribí esta función de Python basada en el código javascript. toma un porcentaje como decimal. También he ajustado el valor para mantener los colores más rojos durante más tiempo en la escala porcentual. También reduje la gama de colores de 255 a 180 para dar un rojo más oscuro y verde en cada extremo. estos se pueden jugar para dar bonitos colores. Me gustaría agregar un toque de naranja en el medio, pero tengo que seguir con el trabajo adecuado, abucheo.

def getBarColour(value):
    red = int( (1 - (value*value) ) * 180 )
    green = int( (value * value )* 180 )

    red = "%02X" % red
    green = "%02X" % green

    return '#' + red + green +'00'

Dado que el amarillo es una mezcla de rojo y verde, probablemente puedes comenzar con # F00 y luego deslizar el verde hacia arriba hasta que toques # FF0 , luego deslizar el rojo hacia abajo para # 0F0 :

for (int i = 0; i < 100; i++) {
    var red = i < 50
        ? 255
        : 255 - (256.0 / 100 * ((i - 50) * 2));
    var green = i < 50
        ? 256.0 / 100 * (i * 2)
        : 255;
    var col = Color.FromArgb((int) red, (int) green, 0);
}

Uso las siguientes rutinas de Python para combinar colores:

def blendRGBHex(hex1, hex2, fraction):
    return RGBDecToHex(blendRGB(RGBHexToDec(hex1), 
                                RGBHexToDec(hex2), fraction))

def blendRGB(dec1, dec2, fraction):
    return [int(v1 + (v2-v1)*fraction) 
        for (v1, v2) in zip(dec1, dec2)]

def RGBHexToDec(hex):
    return [int(hex[n:n+2],16) for n in range(0,len(hex),2)]

def RGBDecToHex(dec):
    return "".join(["%02x"%d for d in dec])

Por ejemplo:

>>> blendRGBHex("FF8080", "80FF80", 0.5)
"BFBF80"

Otra rutina envuelve esto para combinar bien entre valores numéricos para " formato condicional " ;:

def colourRange(minV, minC, avgV, avgC, maxV, maxC, v):
    if v < minV: return minC
    if v > maxV: return maxC
    if v < avgV:
        return blendRGBHex(minC, avgC, (v - minV)/(avgV-minV))
    elif v > avgV:
        return blendRGBHex(avgC, maxC, (v - avgV)/(maxV-avgV))
    else:
        return avgC

Entonces, en el caso de Jonas:

>>> colourRange(0, "FF0000", 50, "FFFF00", 100, "00FF00", 25)
"FF7F00"

Mi solución para ActionScript 3:

var red:Number = (percentage <= 50) ? 255 : 256 - (percentage - 50) * 5.12;
var green:Number = (percentage >= 50) ? 255 : percentage * 5.12;

var redHex:Number = Math.round(red) * 0x10000;
var greenHex:Number = Math.round(green) * 0x100;

var colorToReturn:uint = redHex + greenHex;

Debido a que es R-G-B, los colores van desde valores enteros de -1 (blanco) a -16777216 para negro. con rojo verde y amarillo en algún lugar en el medio que. El amarillo es en realidad -256, mientras que el rojo es -65536 y el verde es -16744448. Entonces el amarillo en realidad no está entre rojo y verde en la notación RGB. Sé que en términos de longitudes de onda, el verde está en un lado y el rojo está en el otro lado del espectro, pero nunca he visto este tipo de notación usado en las computadoras, ya que el espectro no representa todos los colores visibles.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top