Generate colors between red and green for a power

2020-01-25 12:19发布

I'm writing a Java game and I want to implement a power meter for how hard you are going to shoot something.

I need to write a function that takes a int between 0 - 100, and based on how high that number is, it will return a color between Green (0 on the power scale) and Red (100 on the power scale).

Similar to how volume controls work:
volume control

What operation do I need to do on the Red, Green, and Blue components of a color to generate the colors between Green and Red?

So, I could run say, getColor(80) and it will return an orangish color (its values in R, G, B) or getColor(10) which will return a more Green/Yellow RGB value.

I know I need to increase components of the R, G, B values for a new color, but I don't know specifically what goes up or down as the colors shift from Green-Red.


Progress:

I ended up using HSV/HSB color space because I liked the gradiant better (no dark browns in the middle).

The function I used was:

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

Where "power" is a number between 0.0 and 1.0. 0.0 will return a bright red, 1.0 will return a bright green.

Java Hue Chart:
Java Hue Chart

19条回答
▲ chillily
2楼-- · 2020-01-25 12:48

Off the top of my head, here is the green-red hue transition in HSV space, translated to 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)

The red, green, blue values in the above example are percentages, you'd probably want to multiply them by 255 to get the most used 0-255 range.

查看更多
一纸荒年 Trace。
3楼-- · 2020-01-25 12:48

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

Percent is of course value / max_value. Or if your scale doesn't begin at 0 then (value - min_value) / (max_value - min_value).

查看更多
Summer. ? 凉城
4楼-- · 2020-01-25 12:50

Here is copy-and-paste solution for Swift and HSV scale:

UIColor initializer accepts hue, saturation and brightness in [0, 1] so for given value from [0, 1] we have:

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)
查看更多
兄弟一词,经得起流年.
5楼-- · 2020-01-25 12:52

Self contained example

<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>
查看更多
对你真心纯属浪费
6楼-- · 2020-01-25 12:53

JavaScript

I am using Google Visualization with bar chart and wanted the bars to be green to red based on a percentage. This turned out to be the cleanest solution I found and works perfectly.

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

Just make sure your percentage is 50 for 50% and not 0.50.

查看更多
爷的心禁止访问
7楼-- · 2020-01-25 12:56

This should work - just linearly scale the red and green values. Assuming your max red/green/blue value is 255, and n is in range 0 .. 100

R = (255 * n) / 100
G = (255 * (100 - n)) / 100 
B = 0

(Amended for integer maths, tip of the hat to Ferrucio)

Another way to do would be to use a HSV colour model, and cycle the hue from 0 degrees (red) to 120 degrees (green) with whatever saturation and value suited you. This should give a more pleasing gradient.

Here's a demonstration of each technique - top gradient uses RGB, bottom uses HSV:

http://i38.tinypic.com/29o0q4k.jpg

查看更多
登录 后发表回答