在JavaScript中生成随机颜色的最佳方法是什么?

53

如何在JavaScript中生成随机颜色,不使用任何框架...

以下是我想到的一些解决方案:

function get_random_color() 
{
    var color = "";
    for(var i = 0; i < 3; i++) {
        var sub = Math.floor(Math.random() * 256).toString(16);
        color += (sub.length == 1 ? "0" + sub : sub);
    }
    return "#" + color;
}

function get_rand_color()
{
    var color = Math.floor(Math.random() * Math.pow(256, 3)).toString(16);
    while(color.length < 6) {
        color = "0" + color;
    }
    return "#" + color;
}

还有更好的方法吗?


7
如果你需要生成大量可区分颜色以供人类使用,建议使用随机HSV(参见http://en.wikipedia.org/wiki/HSL_and_HSV)值。这是因为你可以在S和V上提供较少的可能性,但仍能得到外观不同的颜色。 - George Phillips
1
可能是JavaScript中的随机颜色生成器的重复问题。 - Damjan Pavlica
10个回答

134

更简短的方式:

'#'+(0x1000000+Math.random()*0xffffff).toString(16).substr(1,6)

1
确实是非常简短的解决方案 =) 我本来想给你点赞的,但我发现在 Math.random 返回 0.00.5 这种极其罕见的情况下会出问题。 - Blixt
1
是的,现在应该没问题了(而且非常接近你的解决方案但更短 :) - Franck Freiburger
1
+1:使用相同的风格(即运算符之间的空格等),您的代码大约缩短了35个字符=)这是我用于比较的格式化版本:return '#' + (0x1000000 + Math.random() * 0xFFFFFF).toString(16).substr(1,6); - Blixt
1
Soubok,你介意我在javascriptcookbook.com上使用你的解决方案吗?一位读者认为这将是一个不错的补充。 - Raymond Camden
1
如果你想生成大量的随机颜色(百万级别),那么将数字取整会快上一个数量级(因为toString需要更少地处理整数):'#' + (0x1000000 + Math.floor(Math.random() * 0x1000000)).toString(16).substr(1);(请注意,乘法必须是0x1000000而不是0xFFFFFF,因为Math.random返回范围为[0, 1),也就是说,它永远不会返回1.0)。https://jsperf.com/random-hex-color - Blixt
显示剩余3条评论

16

这里有一种生成随机颜色并提供最小亮度的方法:

function randomColor(brightness){
  function randomChannel(brightness){
    var r = 255-brightness;
    var n = 0|((Math.random() * r) + brightness);
    var s = n.toString(16);
    return (s.length==1) ? '0'+s : s;
  }
  return '#' + randomChannel(brightness) + randomChannel(brightness) + randomChannel(brightness);
}

使用 0-255 的值调用 randomColor,表示颜色的亮度。这对于生成粉彩色很有帮助,例如 randomColor(220)


1
这是我迄今为止看到的基于HSV运作的最佳代码。干得好!如果您想在页面上使用随机亮色,请使用它。这里有一些进一步的阅读材料:http://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/ - Faiz

14

我喜欢你的第二个选项,虽然可以再简化一点:

// Math.pow is slow, use constant instead.
var color = Math.floor(Math.random() * 16777216).toString(16);
// Avoid loops.
return '#000000'.slice(0, -color.length) + color;

1
我认为 substr 并没有被弃用,但它比 substringslice 标准性较低。值得注意的是,substr 的行为与 substring 不同。无论如何,我改用 slice 是因为它使代码更简单,这是额外的好处。=) - Blixt
2
"#" + ("000000" + Math.floor(Math.random() * 16777216).toString(16)).substr(-6); - wronex

12

在其他答案的帮助下,我是这样做的:

'#' + parseInt(Math.random() * 0xffffff).toString(16)

0.06029829654625929 => #f6fb5, 0.01086451193560456 => #2c804, 0.013915316490329177 => #38ff4, 0.0421506948772119 => #aca63, 0.0067180071741699265 => #1b845, 0.02415522842446105 => #62f09, 0.01397159804923187 => #393a4, 0.01909063159540958 => #4e31f - gaitat
#333与#333333是相同的颜色 - 这并不是真正的随机。 - Ruben Serrate

9

正如George所说的那样,最好的方法是使用HSL,这样你可以生成一堆随机的人类可辨别颜色。类似的想法在Adams Cole answer中的类似问题中得到了实现,但他的代码将随机颜色生成器和hsl->hex rgb转换器捆绑在一起,这使得理解和修改变得困难。

如果您使用其中一个JavaScript颜色处理库(如jquery-color),则颜色生成变得微不足道:

function rainbow() {
  // 30 random hues with step of 12 degrees
  var hue = Math.floor(Math.random() * 30) * 12;

  return $.Color({
    hue: hue,
    saturation: 0.9,
    lightness: 0.6,
    alpha: 1
  }).toHexString();
};

有没有可能“添加”另一种颜色,并且基本上让它从上次离开的地方继续?例如,假设您开始有30个要着色的项目,但用户添加了第31个项目。是否有一种方法可以让它继续使用当前生成的设置,并简单地生成第31种颜色,以符合先前的色调和步骤? - Spectator6

6
更简洁:
function get_random_color2() 
{
    var r = function () { return Math.floor(Math.random()*256) };
    return "rgb(" + r() + "," + r() + "," + r() + ")";
}

1
你应该在 get_random_color2 函数外定义函数... 每次调用重新定义函数感觉有点不必要。之前链接的解决方案更好,因为它只调用了一次 Math.random,然后使用位移来获取红/绿/蓝三个分量。 - Blixt
@Blixt 这是你所说的内容:function randomRGB(){ var c = Math.random()*16777215; return 'rgb('+((c >> 16) & 0xff)+','+((c >> 8) & 0xff)+','+(c & 0xff)+')'; } - George

4
function randomColor()
{
     color='rgb('+Math.round(Math.random()*255)+','+Math.round(Math.random()*255)+','+Math.round(Math.random()*255)+')';

     return color;
}

这将返回一个随机的RGB值。


3

这个答案是最好的方法。

你应该提供已知的颜色供选择,而不是仅依赖纯数字方法。你可以使用像ColorBrewer这样的网站来选择适合问题的颜色调色板(定性数据集、定量数据集等)。

['red','orange','yellow','green','blue','purple'][Math.random()*6|0]

var colors = {
  rainbow: ['red', 'orange', 'yellow', 'green', 'blue', 'purple'],
  qual: ['#8dd3c7', '#ffffb3', '#bebada', '#fb8072', '#80b1d3', '#fdb462', '#b3de69', '#fccde5', '#d9d9d9', '#bc80bd', '#ccebc5', '#ffed6f'],
  quant: ['#fff7ec', '#fee8c8', '#fdd49e', '#fdbb84', '#fc8d59', '#ef6548', '#d7301f', '#b30000', '#7f0000'],
  div: ['#67001f','#b2182b','#d6604d','#f4a582','#fddbc7','#f7f7f7','#d1e5f0','#92c5de','#4393c3','#2166ac','#053061']
};
randc = function(array) {
  return array[Math.random() * array.length | 0]
}
genc = function() {
  var frag = [];
  var arr = colors[$("select").val()];
  for (var i = 0; i < 1024; i++) {
    frag.push("<div style='background-color:" + randc(arr) + ";'></div>");
  }
  $("#demo").html(frag.join(''));
}
genc();
$("select").on("change", genc);
#demo {
  margin-top: 10px;
  font-size: 0;
}
#demo div {
  display: inline-block;
  width: 24px;
  height: 24px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select>
  <option value='qual'>Qualitative (categorical)</option>
  <option value='quant'>Quantitative (sequential)</option>
  <option value='div'>Divergent (republicans versus democrats)</option>
  <option value='rainbow'>Rainbow (my little pony)</option>
</select>
<div id='demo'></div>


请更新并说明为什么这个答案是正确的。 - Adam Buchanan Smith

1

2
这将经常返回无效的颜色,Math.random() 返回的小数位数变化很大。在 FF 中,它返回超过 6 位数字的字符串,而 Chrome/Safari 可以低至 2 位数字。 - bryc

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接