使用随机的颜色生成器作为种子时,过滤某些颜色

时间:2019-06-20 16:40:57

标签: javascript random colors

目前,我产生了一种非常满意的随机颜色。在大多数情况下,颜色很吸引人,并且种子数据部分按预期工作。

问题是,我需要防止显示白色和黑色。实际上,我想忽略任何白色阴影,也不要因为黑色而摇摆不定的任何颜色。

这是我的功能:

seededColorGenerator = (id, delivery_id) => {
if (delivery_id) {
    return '#' + Math.floor((Math.abs(Math.sin(delivery_id) * 16777215)) % 16777215).toString(16)
} else{
    return '#' + Math.floor((Math.abs(Math.sin(id) * 16777215)) % 16777215).toString(16)
      }
}

我正在考虑显式地挑选颜色值并将它们存储到数组中,然后遍历它们以检查是否返回了所述颜色,如果是,请再次调用该算法以获取另一种随机颜色。我不确定这是否是最佳做法。

有什么想法吗?我知道关于随机颜色生成器的讨论很多,但是我还没有看到与它们相关的良好过滤过程。

3 个答案:

答案 0 :(得分:1)

如果您的颜色不是很多(<1000),我建议您使用静态颜色数组,该数组可以轻松过滤以避免此类琐碎运算的数学计算。

当然,您可以第一次使用数学方法初始化该数组。

答案 1 :(得分:1)

一种简单的方法是实施seeded pseudorandom number generator (PRNG)并使用该PRNG生成从0到255的三个数字,直到这些数字的平均值大于30(不接近黑色)且小于220(不接近白色)。这不是避免“白色”或“黑色”颜色的最佳算法 (mx-mn) / (mx+mn)小于0.2(接近灰色),其中mn和{ {1}}是其中最小和最大的数字。这不是避免“灰色”颜色的最佳算法(因为它没有考虑人类色彩感知和色彩空间的复杂问题),但对于您的目的来说可能“足够好”。从这种意义上讲,根据需要调整值30和220 值0.2 。有关找到颜色色度(相对饱和度)的更好算法,请参见this article

请注意,存在某些问题:

  • 除非mxid可以覆盖超过24位的状态空间(也就是说,delivery_idid的可能值超过2 ^ 24 ),某些给定的PRNG或哈希函数将无法生成某些颜色。
  • 如果delivery_id的现有代码生成的“随机”数字小于2 ^ 20,则您生成的seededColorGenerator字符串可能少于6个16位数字,这可能以1/16的机会发生。这是因为toString(16)在将数字转换为基数16时不进行零填充。

编辑(6月24日):经过询问者的澄清,进行了编辑。

答案 2 :(得分:1)

您似乎正在使用十六进制值作为颜色代码?如果您将十六进制值分成三部分,则您有R G B。

然后将R G B组件相互检查。对于白色/黑色,它们的大小都等于FFFFFF或000000。深色或基本黑色的颜色将接近0并且具有足够的值,您可以添加额外的检查以防止这些值通过。

例如,如果它们都在30以下,则查找新号码。另外,如果您有兴趣消除灰色,这些颜色也将具有相似的RGB值,例如 A1-B2-C2为蓝灰色。但是,当这些值彼此接近时,它们的饱和度就会降低。例如。 A1-B2-B2。稍微摆弄数字,您应该就能弄清楚自己想要它们的饱和度/亮度。

其中大部分可以通过if语句或switch语句完成,只需一点点递归即可再次调用该函数,以重复搜索其他颜色。

此过程中最烦人的部分是转换为十六进制,获取最后两位数字,然后转换回十进制以使用适当的值。其他人可能有一个更简单的方法。


x = Math.floor((Math.abs(Math.sin(delivery_id) * 16777215)) % 16777215).toString(16)
a = parseInt(x.slice(-2), 16)
b = parseInt(x.slice(2, 4), 16)
c = parseInt(x.slice(0,2),16) 

这将为您提供RGB的三个十进制值。您可能可以用它们的原始十六进制对其进行操作,尽管我还没有使用Javascript来解决这些问题。您可以像使用toString(16)一样将它们转换回十六进制,然后连接字符串并将#符号添加到前面。

以下是您可以使用的if结构的示例:

#Check for values too close to each other (unsaturated colors)
if (Math.abs(a-b)>30 && Math.abs(a-c) > 30 && Math.abs(b-c) > 30)
{
    seededColorGenerator(Math.random())
}
#check for colors that are too bright or too dark
else if ((a < 30 && b < 30 && c < 30) || (a < 225 && b < 225 && c > 225))
{
    seededColorGenerator(Math.random())
}
#Assuming the color was not dark/bright or unsaturated return it. 
else
{
    return '#' + x.toString(16)
}