题
将百分比转换为从绿色 (100%) 到红色 (0%)(黄色为 50%)的颜色的最简单方法是什么?
我使用的是普通 32 位 RGB - 因此每个分量都是 0 到 255 之间的整数。我用 C# 来做这件事,但我想对于这样的问题,语言其实并不那么重要。
根据 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);
工作完美 - 我必须从 Marius 解决方案中进行的唯一调整是使用 256,因为 (255 - (百分比 - 50) * 5.12 产量 -1 当 100% 时,由于某种原因在 Silverlight 中导致黄色 (-1, 255, 0 ) -> 黄色...
解决方案
我在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)";
}
其他提示
您可能想要做的是在 HSV 或 HSL 颜色空间中分配 0% 到 100% 的一些点。从那里你可以插入颜色(黄色恰好位于红色和绿色之间:)并且 将它们转换为 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) 和您可能需要稍微调整颜色以适合您的目的(有些人不喜欢红色和绿色不“纯”)。
请参见:
- 使用 HSL 颜色(色调、饱和度、亮度)创建更好看的 GUI 进行一些讨论和
- RGB 和 HSL 色彩空间转换 示例 C# 源代码。
用伪代码来说。
从 0-50%,您的十六进制值将为 FFxx00,其中:
XX = ( Percentage / 50 ) * 255 converted into hex.
从 50 到 100,您的十六进制值为 xxFF00,其中:
XX = ((100-Percentage) / 50) * 255 converted into hex.
希望有帮助并且可以理解。
这是一个很好的干净的解决方案,它通过以下三种方式改进了当前接受的答案:
- 删除了幻数 (5.12),从而使代码更易于理解。
- 当百分比为 100% 时,不会产生 -1 的舍入误差。
- 允许您自定义使用的最小和最大 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%。
我根据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'
由于黄色是红色和绿色的混合,您可以从#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);
}
我使用以下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"
我的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;
因为它是R-G-B,颜色从-1(白色)的整数值变为黑色的-16777216。在中间的某个地方有红绿色和黄色。黄色实际为-256,红色为-65536,绿色为-16744448。因此RGB表示法中的黄色实际上不在红色和绿色之间。我知道就波长而言,绿色位于一侧,红色位于光谱的另一侧,但我从未在计算机中看到过这种类型的表示法,因为光谱并不代表所有可见的颜色。