如何创建代表颜色的随机十六进制字符串?
Posted
技术标签:
【中文标题】如何创建代表颜色的随机十六进制字符串?【英文标题】:How do I create a random hex string that represents a color? 【发布时间】:2010-10-18 08:29:55 【问题描述】:我正在生成一些需要十六进制字符串作为颜色的图表。
例子:
<dataseries name="ford" color="FF00FF" />
我是动态创建的,所以我想为每个数据序列随机生成十六进制代码。
最好的方法是什么?
【问题讨论】:
我只是注意到我的例子没有通过。我猜那是因为它是一个 xml 字符串......哦,好吧,没关系,因为答案很好。 @rahkim - 更新问题以解决该问题并添加更有意义的标题 【参考方案1】:最简单的方法是使用String.Format
并使用十六进制格式的参数。
var random = new Random();
var color = String.Format("#0:X6", random.Next(0x1000000)); // = "#A197B9"
【讨论】:
我知道,我首先考虑使用数组和选择元素,然后我记得 String.Format 可以做十六进制。 如果我错了,请纠正我,但是使用该代码,您将永远不会生成值 0xFFFFFF,因为您传递给 Next 方法的整数是不包含在内的上限。所以你需要 random.Next(0x1000000) 才能返回 0xFFFFFF。 一件有趣的事;如果我在设置颜色时设置断点,每次循环都会产生不同的颜色。如果我让它运行,asp 页面会给我所有相同的颜色。 @rahkim:那是因为生成器是用时钟时间播种的。在一个循环中,每个 Random 的生成速度都非常快,以至于它们都使用相同的种子。当你打破时,有足够的时间使用新的种子。尝试在整个循环中重用 Random 对象。 或var color = $"#random.Next(0x1000000):X6";
在 C# 6 中使用字符串插值。【参考方案2】:
Samuel 的回答是做到这一点的最佳方式,只要确保如果您在循环内生成颜色,您不会每次都实例化一个新的 Random
对象,因为 new Random()
使用系统时钟。您的循环运行速度将超过时钟的滴答速度,因此您最终会一遍又一遍地生成几种相同的颜色,因为 random
正在使用相同的值播种。
它应该看起来像这样:
int numColors = 10;
var colors = new List<string>();
var random = new Random(); // Make sure this is out of the loop!
for (int i = 0; i < numColors; i++)
colors.Add(String.Format("#0:X6", random.Next(0x1000000)));
代替:
int numColors = 10;
var colors = new List<string>();
for (int i = 0; i < numColors; i++)
var random = new Random(); // Don't put this here!
colors.Add(String.Format("#0:X6", random.Next(0x1000000)));
【讨论】:
这解释了为什么 rahkim 在使用断点时会得到随机颜色。大声笑 我什至没有想到。您是否出于某种原因将颜色添加到列表中?只是好的做法,还是我缺少什么? 这只是一个例子,因为我不确定他是如何分配它们的【参考方案3】:IMO,纯粹随机的颜色可能并不可取,因为您需要人眼可分辨的颜色。
如何预设一些颜色并随机选择?
也许您可以在一些开源图表库中找到更好的答案。
【讨论】:
这将是首选方法,但也许 OP 有其他完全随机颜色的原因。 我想到了这一点,因为有些颜色可能会混合在一起。我不确定要预设多少,因为我可以拥有非常多的系列。 预设和随机的混合可能会有所帮助。仔细预设大约 10 种好看的颜色。如果不止于此,请随机选择。一般来说,未经训练的眼睛开始在过度着色的图表中感到困惑,所以使用的确切颜色并不重要【参考方案4】:生成一组漂亮颜色的一个好方法是使用固定的饱和度和亮度来定义它们,并改变色调。
-
将饱和度和亮度设置为您喜欢的值,例如 50% 饱和度和 90% 亮度。
现在将 360 度色调除以您想要的不同颜色的数量。
使用色调间隔和固定的 S 和 V 从 HSV 中挑选颜色。
这为您提供了一组漂亮的颜色,它们看起来都来自同一个“集合”——全是柔和的,或全是浓烈的,或全是灰白色的,等等。如果你有 Color.FromHSV() 的话,编码就很容易了。
但是,一旦您获得太多颜色,它可能会停止工作,它们将无法区分。但无论如何,你可能会遇到这个问题。
在伪代码中:
Sat = 0.5 * 255 //assuming we want range 0-255...
Brightness = 0.9 * 255
NumberOfColours = 7
HueSeparation = 360 / 7
Colors = []
for (i = 0 ; i< NumberOfColours; i++)
Colors.Add(Color.FromHSV(HueSeparation * i, Sat, Brightness)
或
n = 7
Colors = [Color.FromHSV(x*360/n, 128, 230) for x in range(n)]
(我确实喜欢列表推导式...)
【讨论】:
【参考方案5】:Random rand = new Random(); // specify a seed
int r = rand.Next(0x1000000);
Console.WriteLine("#0:X6", r);
【讨论】:
这不处理低值。 0x00FFFF 变成 #FFFF 和 #00FFFF 不同。【参考方案6】:我注意到您 (Rahkim) 对 Greg 的帖子发表了评论,说您希望您可以将他的想法(保持饱和度和值不变,并且只是改变色调......一个好主意)放入代码中。你可以!或者,更确切地说,有人已经为你准备好了!
我在Converting HSV to RGB colour using C# 上找到了这篇博文,我相信还有更多。与完全随机选择它们相比,您可能会以这种方式获得更好的颜色套件。
此外,当然,这种方法可以很容易地获得一组漂亮的颜色......因为色调从 0 到 359,你可以做一些像这样设置你的色调的事情:
Hue = (PreviousHue + 50) % 360;
(我选择 50 是因为它不会均匀地进入 360,所以如果你超过 360,你不会立即开始重复色调。你必须玩弄这个值以获得理想的分离,具体取决于如何你期待的许多不同的颜色。)
这样您就不必担心当仍有大量未使用的“色调”空间时,代码会随机选择两种非常接近的颜色。
【讨论】:
我喜欢这个。它给了我一些灵活性。以上是关于如何创建代表颜色的随机十六进制字符串?的主要内容,如果未能解决你的问题,请参考以下文章