C# 条件格式——颜色转换的百分比

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25007/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-01 09:14:02  来源:igfitidea点击:

Conditional formatting -- percentage to color conversion

提问by Jonas Folles?

What's the easiest way to convert a percentage to a color ranging from Green (100%) to Red (0%), with Yellow for 50%?

将百分比转换为从绿色 (100%) 到红色 (0%)、黄色为 50% 的颜色的最简单方法是什么?

I'm using plain 32bit RGB - so each component is an integer between 0 and 255. I'm doing this in C#, but I guess for a problem like this the language doesn't really matter that much.

我使用的是普通的 32 位 RGB - 所以每个组件都是 0 到 255 之间的整数。我在 C# 中这样做,但我想对于这样的问题,语言并不重要。

Based on Marius and Andy's answers I'm using the following solution:

根据 Marius 和 Andy 的回答,我使用了以下解决方案:

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

Works perfectly - Only adjustment I had to make from Marius solution was to use 256, as (255 - (percent - 50) * 5.12 yield -1 when 100%, resulting in Yellow for some reason in Silverlight (-1, 255, 0) -> Yellow ...

完美运行 - 我必须从 Marius 解决方案中进行的唯一调整是使用 256,如 (255 - (percent - 50) * 5.12 yield -1 when 100%,由于某种原因在 Silverlight (-1, 255, 0 ) -> 黄色 ...

采纳答案by Marius

I made this function in JavaScript. It returns the color is a css string. It takes the percentage as a variable, with a range from 0 to 100. The algorithm could be made in any language:

我用 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)";
}

回答by Konrad Rudolph

As yellow is a mix of red and green, you can probably start with #F00and then slide green up until you hit #FF0, then slide red down to #0F0:

由于黄色是红色和绿色的混合体,您可以先从 开始,#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);
}

回答by Cade

In pseudocode.

在伪代码中。

  • From 0-50% your hex value would be FFxx00 where:

    XX = ( Percentage / 50 ) * 255 converted into hex.
    
  • From 50-100 your hex value would be xxFF00 where:

    XX = ((100-Percentage) / 50) * 255 converted into hex.  
    
  • 从 0-50% 开始,您的十六进制值为 FFxx00,其中:

    XX = ( Percentage / 50 ) * 255 converted into hex.
    
  • 从 50 到 100,您的十六进制值为 xxFF00,其中:

    XX = ((100-Percentage) / 50) * 255 converted into hex.  
    

Hope that helps and is understandable.

希望有所帮助并且可以理解。

回答by Kibbee

Because it's R-G-B, the colors go from integer values of -1 (white), to -16777216 for black. with red green and yellow somewhere in the middle that. Yellow is actually -256, while red is -65536 and green is -16744448. So yellow actually isn't between red and green in the RGB notation. I know that in terms of wavelenghts, green is on one side, and red is on the other side of the spectrum, but I've never seen this type of notation used in computers, as the spectrum doesn't represent all visible colours.

因为它是 RGB,所以颜色从整数值 -1(白色)到 -16777216 的黑色。中间有红色绿色和黄色。黄色实际上是-256,而红色是-65536,绿色是-16744448。所以黄色实际上不在RGB表示法中的红色和绿色之间。我知道就波长而言,绿色在光谱的一侧,红色在光谱的另一侧,但我从未在计算机中看到过这种类型的符号,因为光谱并不代表所有可见的颜色。

回答by Henrik Gustafsson

What you probably want to do is to assign your 0% to 100% some points in a HSV or HSL color-space. From there you can interpolate colors (and yellow just happens to be between red and green :) and convert them to RGB. That will give you a nice looking gradient between the two.

您可能想要做的是在 HSV 或 HSL 颜色空间中分配 0% 到 100% 的某些点。从那里你可以插入颜色(黄色恰好介于红色和绿色之间:)并将它们转换为 RGB。这将为您提供两者之间的漂亮渐变。

Assuming that you will use the color as a status indicator and from a user-interface perspective, however, that is probably not such a good idea, since we're quite bad at seeing small changes in color. So dividing the value into, for example, three to seven buckets would give you more noticeable differences when things change, at the cost of some precision (which you most likely would not be able to appreciate anyway).

假设您将使用颜色作为状态指示器并从用户界面的角度来看,然而,这可能不是一个好主意,因为我们很难看到颜色的微小变化。因此,例如,将值分成三到七个桶会在情况发生变化时为您提供更明显的差异,但代价是某些精度(无论如何您很可能无法欣赏)。

So, all the math aside, in the end I'd recommend a look-up-table with the following colors with v being the input value:

所以,抛开所有的数学,最后我会推荐一个具有以下颜色的查找表,其中 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%

These have been very na?vely converted from HSL values (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), and you might want to adjust the colors somewhat to suit your purposes (some don't like that red and green aren't 'pure').

这些已经非常简单地从 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) 转换而来,并且您可能想要稍微调整颜色以适合您的目的(有些人不喜欢红色和绿色不是“纯色”)。

Please see:

请参见:

回答by Tom

I use the following Python routines to blend between colours:

我使用以下 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])

For example:

例如:

>>> blendRGBHex("FF8080", "80FF80", 0.5)
"BFBF80"

Another routine wraps this to blend nicely between numerical values for "conditional formatting":

另一个例程将其包装起来以在“条件格式”的数值之间很好地融合:

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

So, in Jonas' case:

所以,在乔纳斯的情况下:

>>> colourRange(0, "FF0000", 50, "FFFF00", 100, "00FF00", 25)
"FF7F00"

回答by Tom

I wrote this python function based on the javascript code. it takes a percentage as a decimal. also i have squared the value to keep the colours redder for longer down the percentage scale. I also narrowed the range of colours from 255 to 180 to give a darker red and green at each end. these can be played with to give nice colours. I'd like to add a touch of orange in the middle, but i gotta get on with proper work, boo.

我根据javascript代码编写了这个python函数。它需要一个百分比作为小数。我还对值进行了平方,以使颜色在百分比范围内更长时间保持红色。我还将颜色范围从 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'

回答by Simon

My solution for ActionScript 3:

我的 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;

回答by Mark Whitaker

This is a nice clean solution that improves on the currently accepted answer in three ways:

这是一个很好的干净的解决方案,它在三个方面改进了当前接受的答案:

  1. Removes the magic number (5.12), therefore making the code easier to follow.
  2. Won't produce the rounding error that's giving you -1 when the percentage is 100%.
  3. Allows you to customise the minimum and maximum RGB values you use, so you can produce a lighter or darker range than simple rgb(255, 0, 0) - rgb(0, 255, 0).
  1. 删除幻数 (5.12),从而使代码更易于理解。
  2. 当百分比为 100% 时,不会产生给您 -1 的舍入误差。
  3. 允许您自定义您使用的最小和最大 RGB 值,因此您可以生成比简单的 rgb(255, 0, 0) - rgb(0, 255, 0) 更亮或更暗的范围。

The code shown is C# but it's trivial to adapt the algorithm to any other language.

显示的代码是 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);
}

Notes

笔记

Here's a simple table showing some percentage values, and the corresponding red and green proportions we want to produce:

这是一个简单的表格,显示了一些百分比值,以及我们想要生成的相应红色和绿色比例:

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

Hopefully you can see pretty clearly that

希望你能清楚地看到

  • the green value is 2x the percentage value (but capped at 100)
  • the red is the inverse: 2x (100 - percentage) (but capped at 100)
  • 绿色值是百分比值的 2 倍(但上限为 100)
  • 红色是相反的:2x(100 - 百分比)(但上限为 100)

So my algorithm calculates the values from a table looking something like this...

所以我的算法从一个看起来像这样的表中计算值......

VALUE   GREEN    RED
 100%    200%     0%
  75%    150%    50%
  50%    100%   100%
  25%     50%   150%
   0%      0%   200%

...and then uses Math.Min()to cap them to 100%.

...然后使用Math.Min()将它们限制为 100%。