Генерировать цвета между красным и зеленым для счетчика мощности?
Я пишу Java-игру, и я хочу реализовать измеритель мощности для того, насколько сильно вы собираетесь что-то снимать.
мне нужно написать функцию, которая принимает int между 0-100, и на основе того, насколько высоко это число, оно вернет цвет между зеленым (0 на шкале мощности) и красным (100 на шкале мощности).
аналогично тому, как работают регуляторы громкости:
какую операцию мне нужно сделать на красных, зеленых и синих компонентах цвета, чтобы генерировать цвета между зеленым и красным?
Итак, я мог бы побежать сказать,getColor(80)
и он вернет оранжевый цвет (его значения в R, G, B) или getColor(10)
которая будет возвращать более зеленый цвет/желтый цвет значение RGB.
Я знаю, что мне нужно увеличить компоненты значений R, G, B для нового цвета, но я не знаю конкретно, что идет вверх или вниз, когда цвета смещаются от зелено-красного.
прогресса:
Я закончил тем, что использовал цветовое пространство HSV/HSB, потому что мне понравилось градиент лучше (нет темно-коричневых в середине).
функция, которую я использовал, была:
public Color getColor(double power)
{
double H = power * 0.4; // Hue (note 0.4 = Green, see huge chart below)
double S = 0.9; // Saturation
double B = 0.9; // Brightness
return Color.getHSBColor((float)H, (float)S, (float)B);
}
где "Power" - это число между 0.0 и 1.0. 0.0 вернет ярко-красный, 1.0 вернет ярко-зеленый.
Диаграмма Оттенков Java:
19 ответов:
это должно работать - просто линейно масштабировать красные и зеленые значения. Предполагая, что ваше максимальное значение красного / зеленого / синего равно
255
иn
находится в границах0 .. 100
R = (255 * n) / 100 G = (255 * (100 - n)) / 100 B = 0
(исправлено для целочисленной математики, кончик шляпы Ферручио)
другой способ сделать это было бы использовать цветовая модель ВПГ, и цикл оттенок от
0 degrees
(красный) в120 degrees
(зеленый) с любой насыщенностью и значением подходит вам. Это должно дать более приятное уклон.вот демонстрация каждого метода-верхний градиент использует RGB, Нижний использует HSV:
С верхней части моей головы, вот переход зелено-красного оттенка в пространстве HSV, переведенный в RGB:
blue = 0.0 if 0<=power<0.5: #first, green stays at 100%, red raises to 100% green = 1.0 red = 2 * power if 0.5<=power<=1: #then red stays at 100%, green decays red = 1.0 green = 1.0 - 2 * (power-0.5)
красные, зеленые, синие значения в приведенном выше примере являются процентами, вы, вероятно, захотите умножить их на 255, чтобы получить наиболее используемый диапазон 0-255.
короткий ответ Copy'n'Paste...
На Java Std:
int getTrafficlightColor(double value){ return java.awt.Color.HSBtoRGB((float)value/3f, 1f, 1f); }
На Android:
int getTrafficlightColor(double value){ return android.graphics.Color.HSVToColor(new float[]{(float)value*120f,1f,1f}); }
Примечание: значение-это число от 0 до 1, указывающее на состояние от красного до зеленого.
линейная интерполяция между зеленым и красным почти должно работать, за исключением того, что в середине будет мутно-коричневый цвет.
наиболее гибким и наиболее привлекательным решением является наличие файла изображения где-то, который имеет точную цветовую рампу, которую вы хотите. А затем найдите значение пикселя там. Это имеет гибкость, что вы можете настроить градиент, чтобы быть в самый раз.
Если вы все еще хотите сделать это из кода, то это, вероятно, лучше для интерполяции между зеленым и желтым цветами в левой части, а также между желтым и красным на правой стороне. В пространстве RGB зеленый (R=0, G=255, B=0), желтый (R=255, G=255, B=0), красный (R=255, G=0, B=0) - это предполагает, что каждый компонент цвета идет от 0 до 255.
Если вы хотите, чтобы зелено-желто-красное представление, такое как принятый ответ, предложило тогда взглянуть на это.
http://jsfiddle.net/0awncw5u/2/
function percentToRGB(percent) { if (percent === 100) { percent = 99 } var r, g, b; if (percent < 50) { // green to yellow r = Math.floor(255 * (percent / 50)); g = 255; } else { // yellow to red r = 255; g = Math.floor(255 * ((50 - percent % 50) / 50)); } b = 0; return "rgb(" + r + "," + g + "," + b + ")"; } function render(i) { var item = "<li style='background-color:" + percentToRGB(i) + "'>" + i + "</li>"; $("ul").append(item); } function repeat(fn, times) { for (var i = 0; i < times; i++) fn(i); } repeat(render, 100);
li { font-size:8px; height:10px; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script> <ul></ul>
Я сделал небольшую функцию, которая дает вам целое значение RGB на процентах:
private int getGreenToRedGradientByValue(int currentValue, int maxValue) { int r = ( (255 * currentValue) / maxValue ); int g = ( 255 * (maxValue-currentValue) ) / maxValue; int b = 0; return ((r&0x0ff)<<16)|((g&0x0ff)<<8)|(b&0x0ff); }
поэтому, если ваше текущее значение равно 50, а ваше максимальное значение равно 100, эта функция вернет цвет, который вам нужен, поэтому, если вы зацикливаете эту функцию с процентным значением, ваше значение цвета будет переходить от зеленого к красному. Извините за плохое объяснение
принятый ответ даже не ответил на вопрос...
C++
вот простой сегмент кода C++ из моего движка, который линейно и эффективно интерполирует между тремя произвольными цветами:
const MATH::FLOAT4 color1(0.0f, 1.0f, 0.0f, 1.0f); // Green const MATH::FLOAT4 color2(1.0f, 1.0f, 0.0f, 1.0f); // Yellow const MATH::FLOAT4 color3(1.0f, 0.0f, 0.0f, 1.0f); // Red MATH::FLOAT4 get_interpolated_color(float interpolation_factor) { const float factor_color1 = std::max(interpolation_factor - 0.5f, 0.0f); const float factor_color2 = 0.5f - fabs(0.5f - interpolation_factor); const float factor_color3 = std::max(0.5f - interpolation_factor, 0.0f); MATH::FLOAT4 color; color.x = (color1.x * factor_color1 + color2.x * factor_color2 + color3.x * factor_color3) * 2.0f; color.y = (color1.y * factor_color1 + color2.y * factor_color2 + color3.y * factor_color3) * 2.0f; color.z = (color1.z * factor_color1 + color2.z * factor_color2 + color3.z * factor_color3) * 2.0f; color.w = 1.0f; return(color); }
The
interpolation_factor
предполагается, что в границах0.0 ... 1.0
.
Предполагается, что цвета находятся в диапазоне0.0 ... 1.0
(например, для OpenGL).C#
вот та же функция, написанная в C#:
private readonly Color mColor1 = Color.FromArgb(255, 0, 255, 0); private readonly Color mColor2 = Color.FromArgb(255, 255, 255, 0); private readonly Color mColor3 = Color.FromArgb(255, 255, 0, 0); private Color GetInterpolatedColor(double interpolationFactor) { double interpolationFactor1 = Math.Max(interpolationFactor - 0.5, 0.0); double interpolationFactor2 = 0.5 - Math.Abs(0.5 - interpolationFactor); double interpolationFactor3 = Math.Max(0.5 - interpolationFactor, 0.0); return (Color.FromArgb(255, (byte)((mColor1.R * interpolationFactor1 + mColor2.R * interpolationFactor2 + mColor3.R * interpolationFactor3) * 2.0), (byte)((mColor1.G * interpolationFactor1 + mColor2.G * interpolationFactor2 + mColor3.G * interpolationFactor3) * 2.0), (byte)((mColor1.B * interpolationFactor1 + mColor2.B * interpolationFactor2 + mColor3.B * interpolationFactor3) * 2.0))); }
The
interpolationFactor
предполагается, что в границах0.0 ... 1.0
.
Предполагается, что цвета находятся в диапазоне0 ... 255
.
вам нужно линейно интерполировать (LERP) компоненты цвета. Вот как это делается в целом, учитывая начальное значение v0, стоимостью v1, а требуется соотношение (нормированной float между 0.0 и 1.0):
v = v0 + ratio * (v1 - v0)
Это дает v0, когда отношение равно 0,0, v1, когда отношение равно 1,0, и все между ними в других случаях.
вы можете сделать это либо на компонентах RGB, либо с помощью какой-либо другой цветовой схемы, как ВПГ или ЗОЖ. Последние два будут более визуально приятными, так как они работают с оттенками и яркостью, которые лучше соответствуют нашему восприятию цвета.
Я бы сказал, что вы хотите что-то между линейным сегментом в пространстве HSV (который имеет немного слишком яркий желтый цвет в центре) и линейным сегментом в пространстве RGB (который имеет уродливый коричневый цвет в центре). Я бы использовал это, где
power = 0
дадут зеленый,power = 50
даст слегка тусклый желтый цвет, иpower = 100
дам красный.blue = 0; green = 255 * sqrt( cos ( power * PI / 200 )); red = 255 * sqrt( sin ( power * PI / 200 ));
import java.awt.Color; public class ColorUtils { public static Color interpolate(Color start, Color end, float p) { float[] startHSB = Color.RGBtoHSB(start.getRed(), start.getGreen(), start.getBlue(), null); float[] endHSB = Color.RGBtoHSB(end.getRed(), end.getGreen(), end.getBlue(), null); float brightness = (startHSB[2] + endHSB[2]) / 2; float saturation = (startHSB[1] + endHSB[1]) / 2; float hueMax = 0; float hueMin = 0; if (startHSB[0] > endHSB[0]) { hueMax = startHSB[0]; hueMin = endHSB[0]; } else { hueMin = startHSB[0]; hueMax = endHSB[0]; } float hue = ((hueMax - hueMin) * p) + hueMin; return Color.getHSBColor(hue, saturation, brightness); } }
Если вам нужен такой градиент (фактически обратный) в CSS (min version 2.1), вы также можете использовать HSL.
предположим, что вы находитесь в шаблоне AngularJs, а значение-это число от 0 до 1, и вы хотите создать элемент (цвет фона или текста)...
hsl({{ value * 120}}, 50%, 35%)
первое значение: Градусы ( 0-красный, 120-зеленый) Второе значение: насыщенность (50% нейтрально) Третье значение: легкость (50% нейтральных)
хорошая статья здесь
теория Википедия здесь
вот решение для копирования и вставки для Swift и HSV scale:
инициализатор UIColor принимает оттенок, насыщенность и яркость в [0, 1], поэтому для данного стоимостью из [0, 1] у нас есть:
let hue: CGFloat = value / 3 let saturation: CGFloat = 1 // Or choose any let brightness: CGFloat = 1 // Or choose any let alpha: CGFloat = 1 // Or choose any let color = UIColor(hue: hue, saturation: saturation, brightness: brightness, alpha: alpha)
здесь
Objective-C
версия решения Simucal:- (UIColor*) colorForCurrentLevel:(float)level { double hue = level * 0.4; // Hue (note 0.4 = Green) double saturation = 0.9; // Saturation double brightness = 0.9; // Brightness return [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:1.0]; }
где уровень будет значение между
0.0
и1.0
.
Надеюсь, это кому-то поможет!
В Python 2.7:
import colorsys def get_rgb_from_hue_spectrum(percent, start_hue, end_hue): # spectrum is red (0.0), orange, yellow, green, blue, indigo, violet (0.9) hue = percent * (end_hue - start_hue) + start_hue lightness = 0.5 saturation = 1 r, g, b = colorsys.hls_to_rgb(hue, lightness, saturation) return r * 255, g * 255, b * 255 # from green to red: get_rgb_from_hue_spectrum(percent, 0.3, 0.0) # or red to green: get_rgb_from_hue_spectrum(percent, 0.0, 0.3)
процентов-это конечно
value / max_value
. Или если ваш масштаб не начинается с 0, то(value - min_value) / (max_value - min_value)
.
JavaScript
Я использую визуализацию Google с гистограммой и хотел, чтобы бары были зелеными до красного цвета в зависимости от процента. Это оказалось самым чистым решением, которое я нашел и отлично работает.
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)'; }
просто убедитесь, что ваш процент 50 на 50% и не 0.50.
сдержанный пример
<html> <head> <script> //-------------------------------------------------------------------------- function gradient(left, mid, right) { var obj = {} var lt50 = {"r":(mid.r-left.r)/50.0, "g":(mid.g-left.g)/50.0, "b":(mid.b-left.b)/50.0} var gt50 = {"r":(right.r-mid.r)/50.0, "g":(right.g-mid.g)/50.0, "b":(right.b-mid.b)/50.0} obj.getColor = function(percent) { if (percent == 50.0) { return mid; } if (percent < 50.0) { return "rgb("+Math.floor(left.r+lt50.r*percent+0.5)+","+ Math.floor(left.g+lt50.g*percent+0.5)+","+ Math.floor(left.b+lt50.b*percent+0.5)+")"; } var p2 = percent-50.0; return "rgb("+Math.floor(mid.r+gt50.r*p2+0.5)+","+ Math.floor(mid.g+gt50.g*p2+0.5)+","+ Math.floor(mid.b+gt50.b*p2+0.5)+")"; } return obj; } //-------------------------------------------------------------------------- var g_gradient = gradient( {"r":255, "g":20, "b":20}, // Left is red {"r":255, "g":255, "b":20}, // Middle is yellow {"r":20, "g":255, "b":20} ); // right is green //-------------------------------------------------------------------------- function updateColor() { var percent = document.getElementById('idtext').value.length; var oscore = document.getElementById('idscore'); if (percent > 100.0) { percent = 100.0; } if (percent < 0.0) { percent = 0.0; } var col = g_gradient.getColor(percent) oscore.style['background-color'] = col; oscore.innerHTML = percent + '%'; } </script> </head> <body onLoad="updateColor()"> <input size='100' placeholder='type text here' id='idtext' type="text" oninput="updateColor()" /> <br /> <br /> <div id='idscore' style='text-align:center; width:200px; border-style:solid; border-color:black; border-width:1px; height:20px;'> </div> </body> </html>
я обновил принятый ответ, разбив его на первую и вторую половину диапазона (0,100) и заменив 100 максимальным уровнем, чтобы диапазон мог стать динамическим. Результат точно такой же, как и в модели HSV, но все еще с использованием RGB. Ключ должен иметь (255,255,0) в середине, чтобы представлять желтый цвет. Я объединил эту идею в принятом ответе и другом коде VBA, поэтому достигните ее в VBA и используйте в Excel. Я надеюсь, что логика помогает и может быть использована на других языках/ приложения.
Sub UpdateConditionalFormatting(rng As Range) Dim cell As Range Dim max As Integer max = WorksheetFunction.max(rng) For Each cell In rng.Cells If cell.Value >= 0 And cell.Value < max / 2 Then cell.Interior.Color = RGB(255 * cell.Value / (max / 2), 255, 0) ElseIf cell.Value >= max / 2 And cell.Value <= max Then cell.Interior.Color = RGB(255, 255 * ((max) - cell.Value) / (max / 2), 0) End If Next cell End Sub
Ура, Павлин
Это будет варьироваться от красного до желтого, а затем до Зеленого
значение варьируется от 0 до 100-(UIColor*) redToGreenColorWithPosition:(int) value { double R, G; if (value > 50) { R = (255 * (100 - value)/ 50) ; G = 255; }else { R = 255; G = (255 * (value*2)) / 100; } return [UIColor colorWithRed:R/255.0f green:G/255.0f blue:0.0f alpha:1.0f]; }
В. Б.
Public Function GetPercentageColor( _ ByVal iPercent As Long, Optional _ ByVal bOpposit As Boolean) As Long ' 0->100% - Green->Yellow->Red ' bOpposit - Red->Yellow->Green If bOpposit Then iPercent = (100 - iPercent) Select Case iPercent Case Is < 1: GetPercentageColor = 65280 ' RGB(0, 255, 0) Case Is > 99: GetPercentageColor = 255 ' RGB(255, 0, 0) Case Is < 50: GetPercentageColor = RGB(255 * iPercent / 50, 255, 0) Case Else: GetPercentageColor = RGB(255, (255 * (100 - iPercent)) / 50, 0) End Select End Function