Какой самый простой способ преобразовать процентное значение в цвет от зеленого (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 yield -1 при 100%, что по какой-то причине приводит к желтому в Silverlight (-1, 255, 0) ) -> Желтый ...





Поскольку желтый представляет собой смесь красного и зеленого, вы, вероятно, можете начать с #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 до 50% ваше шестнадцатеричное значение будет FFxx00, где:
XX = ( Percentage / 50 ) * 255 converted into hex.
От 50 до 100 ваше шестнадцатеричное значение будет xxFF00, где:
XX = ((100-Percentage) / 50) * 255 converted into hex.
Надеюсь, что это поможет и понятно.
Поскольку это R-G-B, цвета меняются от целых значений -1 (белый) до -16777216 для черного. с красным, зеленым и желтым где-то посередине. Желтый на самом деле -256, красный -65536 и зеленый -16744448. Таким образом, желтый на самом деле не находится между красным и зеленым в обозначении RGB. Я знаю, что с точки зрения длин волн зеленый находится на одной стороне, а красный - на другой стороне спектра, но я никогда не видел, чтобы такой тип обозначений использовался в компьютерах, поскольку спектр не отображает все видимые цвета.
Я сделал эту функцию на 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)";
}
Что вы, вероятно, захотите сделать, так это присвоить от 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) и возможно, вы захотите немного отрегулировать цвета в соответствии с вашими целями (некоторым не нравится, что красный и зеленый не «чистые»).
Посмотри пожалуйста:
Недавно решив ту же проблему, я решил, что разница между оттенками незаметна, как сказал Хенрик. В итоге я просто переключился с 3 цветов и диапазонов.
Я использую следующие подпрограммы 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"
Я написал эту функцию 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'
Мое решение для 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;
Это хорошее чистое решение, которое улучшает принятый в настоящее время ответ тремя способами:
Показанный код написан на 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
Надеюсь, вы довольно ясно видите, что
Итак, мой алгоритм вычисляет значения из таблицы, которая выглядит примерно так ...
VALUE GREEN RED
100% 200% 0%
75% 150% 50%
50% 100% 100%
25% 50% 150%
0% 0% 200%
... а затем использует Math.Min(), чтобы ограничить их до 100%.
Согласен, это гораздо лучшее решение, чем принятый ответ.
если p = 50, будет сгенерировано 256 для красного и зеленого обоих