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条回答
狗以群分
2楼-- · 2020-01-25 12:39

If you need this kind of gradient (actually reversed) in CSS (min version 2.1) you can use HSL, too.

Supposing you are in an AngularJs template and value is a number from 0 to 1 and you want to style an element (background or text color)...

hsl({{ value * 120}}, 50%, 35%)

First value: degrees ( 0 red, 120 green) Second value: saturation (50% is neutral) Third value: lightness (50% neutral)

A nice article here

Theory on Wikipedia here

查看更多
地球回转人心会变
3楼-- · 2020-01-25 12:41

Here is the Objective-C version of Simucal's solution:

- (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];
}

Where level would be a value between 0.0 and 1.0.
Hope this helps someone!

查看更多
神经病院院长
4楼-- · 2020-01-25 12:43

Linearly interpolating between green and red almost should work, except that in the middle there will be muddy brown color.

The most flexible and best looking solution is to have an image file somewhere that has the exact color ramp you want. And then lookup the pixel value in there. This has the flexibility that you can tweak the gradient to be just right.

If you still want to do it from code, then it's probably best to interpolate between green and yellow colors in the left side, and between yellow and red on the right side. In RGB space, green is (R=0, G=255, B=0), yellow is (R=255, G=255, B=0), red is (R=255, G=0, B=0) - this is assuming each color component goes from 0 to 255.

查看更多
SAY GOODBYE
5楼-- · 2020-01-25 12:43
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);
    }
}
查看更多
别忘想泡老子
6楼-- · 2020-01-25 12:44

I have updated the accepted answer by spliting it into first and second half of the (0,100) range and substituting 100 by a max level, so that the range can become dynamic. The result is exactly as with the HSV model, but still using RGB. The key is to have the (255,255,0) in the middle to represent the yellow colour. I have combined this idea in the accepted answer and another VBA code, so achieve it in VBA and use in Excel. I hope the logic helps and can be used in other languages/ applications.

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

Cheers, Pavlin

查看更多
Deceive 欺骗
7楼-- · 2020-01-25 12:45

If you want an green-yellow-red representation like the accepted answer suggests then take a look at this.

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>

查看更多
登录 后发表回答