Условное форматирование - процентное преобразование цвета

Какой самый простой способ преобразовать процентное значение в цвет от зеленого (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) ) -> Желтый ...

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
19
0
13 234
9
Перейти к ответу Данный вопрос помечен как решенный

Ответы 9

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

если p = 50, будет сгенерировано 256 для красного и зеленого обоих

Raj 10.07.2015 00:15

Что вы, вероятно, захотите сделать, так это присвоить от 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 цветов и диапазонов.

Iain M Norman 30.01.2009 18:40

Я использую следующие подпрограммы 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;

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

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

Согласен, это гораздо лучшее решение, чем принятый ответ.

robasaurus 13.01.2015 10:48

Другие вопросы по теме