Условное форматирование - процентное преобразование в цвет - PullRequest
19 голосов
/ 24 августа 2008

Какой самый простой способ преобразовать процент в цвет в диапазоне от зеленого (100%) до красного (0%), с желтым на 50%?

Я использую простой 32-битный RGB - так что каждый компонент представляет собой целое число от 0 до 255. Я делаю это в C #, но я думаю, что для такой проблемы язык на самом деле не имеет большого значения.

Основываясь на ответах Мариуса и Энди, я использую следующее решение:

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);

Работает отлично - Единственная корректировка, которую мне пришлось сделать из решения Marius, заключалась в использовании 256, так как (255 - (процентов - 50) * 5,12 дает -1 при 100%, в результате чего желтый по какой-то причине в Silverlight (-1, 255, 0) -> Желтый ...

Ответы [ 9 ]

13 голосов
/ 24 августа 2008

Я сделал эту функцию в JavaScript. Возвращает цвет строки CSS. Он принимает процент в качестве переменной с диапазоном от 0 до 100. Алгоритм может быть выполнен на любом языке:

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)";
}
6 голосов
/ 24 августа 2008

То, что вы, вероятно, хотите сделать, - это присвоить 0–100% некоторым точкам в цветовом пространстве HSV или HSL. Оттуда вы можете интерполировать цвета (а желтый оказывается между красным и зеленым :) и конвертировать их в RGB . Это даст вам красивый градиент между ними.

Предполагая, что вы будете использовать цвет в качестве индикатора состояния и с точки зрения пользовательского интерфейса, это, вероятно, не очень хорошая идея, поскольку мы довольно плохо видим небольшие изменения цвета. Таким образом, разделение значения, например, на три-семь сегментов даст вам более заметные различия при изменении ситуации за счет некоторой точности (которую вы, скорее всего, не сможете оценить в любом случае).

Итак, если оставить в стороне всю математику, в конце я бы порекомендовал справочную таблицу со следующими цветами, где v - это входное значение:

#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%

Они были очень наивно преобразованы из значений 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 ), и вы, возможно, захотите откорректировать цвета в соответствии с вашими целями (некоторым не нравится, что красный и зеленый не являются «чистыми»).

Пожалуйста, смотрите:

5 голосов
/ 24 августа 2008

в псевдокоде.

  • От 0-50% ваше шестнадцатеричное значение будет FFxx00, где:

    XX = ( Percentage / 50 ) * 255 converted into hex.
    
  • Из 50-100 ваше шестнадцатеричное значение будет xxFF00, где:

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

Надеюсь, что это помогает и понятно.

2 голосов
/ 12 января 2015

Это хорошее чистое решение, которое улучшает принятый в настоящее время ответ тремя способами:

  1. Удаляет магическое число (5.12), что облегчает выполнение кода.
  2. Не приведет к ошибке округления, которая дает вам -1, когда процент составляет 100%.
  3. Позволяет настроить минимальное и максимальное значения RGB, которые вы используете, так что вы можете создать более светлый или более темный диапазон, чем простой rgb (255, 0, 0) - rgb (0, 255, 0).

Показанный код - C #, но адаптировать алгоритм к любому другому языку тривиально.

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);
}

Примечания

Вот простая таблица, показывающая некоторые процентные значения и соответствующие пропорции красного и зеленого, которые мы хотим получить:

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

Надеюсь, вы достаточно ясно увидите, что

  • значение зеленого цвета в 2 раза превышает процентное значение (но ограничено значением 100)
  • красный - обратный: 2x (100%) (но ограничен 100)

Итак, мой алгоритм вычисляет значения из таблицы, выглядящей примерно так ...

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

... а затем использует Math.Min(), чтобы ограничить их до 100%.

1 голос
/ 26 марта 2009

Я написал эту функцию Python на основе кода JavaScript. это занимает процент в виде десятичной дроби. также я возводил в квадрат значение, чтобы цвета оставались более красными в течение более длительного периода времени. Я также сузил диапазон цветов от 255 до 180, чтобы получить более темный красный и зеленый на каждом конце. с ними можно играть, чтобы дать хорошие цвета. Я хотел бы добавить апельсиновый оттенок в середине, но я должен продолжить работу, бу.

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

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

    return '#' + red + green +'00'
1 голос
/ 24 августа 2008

Поскольку желтый представляет собой смесь красного и зеленого, вы, вероятно, можете начать с #F00, а затем двигать зеленым вверх, пока не нажмете #FF0, а затем сместить красный вниз до #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);
}
0 голосов
/ 07 сентября 2010

Мое решение для 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;
0 голосов
/ 04 сентября 2008

Я использую следующие процедуры Python для смешивания цветов:

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])

Например:

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

Другая процедура оборачивает это, чтобы хорошо сочетаться между числовыми значениями для «условного форматирования»:

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

Итак, в случае с Джонасом:

>>> colourRange(0, "FF0000", 50, "FFFF00", 100, "00FF00", 25)
"FF7F00"
0 голосов
/ 24 августа 2008

Поскольку это R-G-B, цвета изменяются от целочисленных значений -1 (белый) до -16777216 для черного. с красным зеленым и желтым где-то посередине, что. Желтый на самом деле -256, в то время как красный -65536 и зеленый -16744448. Таким образом, желтый цвет фактически не находится между красным и зеленым в обозначении RGB. Я знаю, что с точки зрения длины волны зеленый цвет находится на одной стороне, а красный - на другой стороне спектра, но я никогда не видел такого типа обозначений, используемых в компьютерах, поскольку спектр не отражает все видимые цвета.

...