JavaScript 缩短生成随机 CSS 颜色的重复代码

JavaScript shorten repeating code for generating random CSS color

我决定无缘无故地制作一个随机的十六进制颜色生成器。它工作正常,但需要写

var value1 = hexArray[Math.floor(Math.random() * hexArray.length)];" 6次。我怎样才能解决它,所以我不这样做?如果我这样做

var rand1 = rand2 = rand3 ect. = hexArray[Math.floor(Math.random() * hexArray.length)]; 它会打印出所有具有相同 number/letter 的值。有什么建议吗?

    var hexArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 'd', 'e', 'f'];
    var rand1 = hexArray[Math.floor(Math.random() * hexArray.length)];
    var rand2 = hexArray[Math.floor(Math.random() * hexArray.length)];
    var rand3 = hexArray[Math.floor(Math.random() * hexArray.length)];
    var rand4 = hexArray[Math.floor(Math.random() * hexArray.length)];
    var rand5 = hexArray[Math.floor(Math.random() * hexArray.length)];
    var rand6 = hexArray[Math.floor(Math.random() * hexArray.length)];
    var array2 = [rand1, rand2, rand3, rand4, rand5, rand6]
    var value = "#" + array2.join("");

    //ignore this
    $(document).ready(function() {
      $("body").css("background-color", value);
    });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

您不需要分别生成每个十六进制字符。只需生成一个随机数 0 和 2^24 并将其转换为十六进制:

var pad = "00000"
var random = Math.floor(Math.random() * (0x1000000))
var randomHex = random.toString(16)
var color = "#" + pad.substring(0, 6 - randomHex.length) + randomHex

更新:浏览答案 here,有一些不错的技巧,但除了已接受的答案外,颜色要么不是随机的,要么填充得不正确,要么颜色太长。这是另一个在这两个方面都应该正确的版本:

var random = Math.floor(Math.random() * (1<<24))
var color = "#" + ("00000" + random.toString(16)).substr(-6)
var hexArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 'd', 'e', 'f'];
var array2 = [];
for (i = 0; i <= 5; i++) {
  array2.push(hexArray[Math.floor(Math.random() * hexArray.length)]);
}
var value = "#" + array2.join("");

$('div').css("background-color", value);

评论已经提供了简短的答案,但我将在这里详细说明我们是如何做到的。


第 1 部分:

var rand1 = hexArray[Math.floor(Math.random() * hexArray.length)];
var rand2 = hexArray[Math.floor(Math.random() * hexArray.length)];
var rand3 = hexArray[Math.floor(Math.random() * hexArray.length)];
var rand4 = hexArray[Math.floor(Math.random() * hexArray.length)];
var rand5 = hexArray[Math.floor(Math.random() * hexArray.length)];
var rand6 = hexArray[Math.floor(Math.random() * hexArray.length)];

这部分可以更改为使用数组和循环。这可以做到的一个巨大的赠品是你的变量名中有序列号。但是,因为数组通常是从零开始的,所以我不会使用 1-6,而是使用 0-5 作为索引。在我的循环中,我正在计算一个从 0 到 5 的变量(虽然我正在检查它是否是 < 6 而不是 <= 5 以提高可读性 - 很明显它运行了 6 次)并填充阵列。像这样:

var rand = [];
for(var i = 0; i < 6; i++) {
    rand[i] = hexArray[Math.floor(Math.random() * hexArray.length)];
}

然后我们可以改变这个...

var array2 = [rand1, rand2, rand3, rand4, rand5, rand6];

...为此:

var array2 = [rand[0], rand[1], rand[2], rand[3], rand[4], rand[5]];

...这没什么意义,可以用另一个循环代替:

for(var i = 0; i < rand.length; i++) array2[i] = rand[i];

现在这基本上只是将整个数组rand复制到array2,所以我们可以将其简化为:

var array2 = rand;

好的,但现在总的来说是这样的:

var rand = [];
for(var i = 0; i < 6; i++) {
    rand[i] = hexArray[Math.floor(Math.random() * hexArray.length)];
}
var array2 = rand;

应该清楚我们可以从一开始就使用 array2,或者 - 更有意义的是因为变量名更有意义 - 我们可以继续使用 rand 而不是创建一个新数组 array2,因此我们将更改此...

var value = "#" + array2.join("");

...为此:

var value = "#" + rand.join("");

作为最后的改进,不是总是指定我们要在上面的循环中创建的数组元素 (rand[i] = ...),我们可以继续推入数组 (rand.push(...)),这将每次自动创建一个 ID 递增的新元素:

var rand = [];
for(var i = 0; i < 6; i++) {
    rand.push(hexArray[Math.floor(Math.random() * hexArray.length)]);
}

因此,此时代码如下所示:

var hexArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 'd', 'e', 'f'];
var rand = [];
for(var i = 0; i < 6; i++) {
    rand.push(hexArray[Math.floor(Math.random() * hexArray.length)]);
}
var value = "#" + rand.join("");

//ignore this
$(document).ready(function() {
  $("body").css("background-color", value);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

这应该已经回答了您最初的问题,因为它删除了重复。但是等等,我们能做的还有更多!


第 2 部分:

你用hexArray所做的实际上是试图生成一个随机的十六进制数字。既然我把它放到这句话中,就应该清楚实际上我们可以用更简单的方法来做到这一点:生成一个随机值并将其转换为它的十六进制表示!

可以使用 Math.random() 生成一个随机值,它将输出一个大于或等于零且小于一的随机值(例如 0.292835430.917240.18283123255,你懂的)。

为了获得介于零和另一个值之间的随机数,我们可以将 Math.random() 的结果乘以唯一的最大值,在我们的例子中是 16。

Math.random() * 16 会给出像 3.18237214.22229355.190023 这样的数字,这几乎是我们想要的,但我们只想得到整数(没有小数部分)。我们通过将结果输入 Math.floor 来得到它,它向下舍入,所以 Math.floor(Math.random() * 16) 会给出像 3145 这样的东西,这正是我们需要的.

这基本上就是你已经在做的,因为 hexArray.length16! 我只是解释了一下,因为有人可能会开始使用 someArray[Math.floor(Math.random() * someArray.length)] 没有真正理解它是如何工作的成语。

但是,当我们只是将我们得到的数字填充到一个字符串中时,它们将是十进制的。我们希望它们以十六进制表示,这样前面示例中的 14 将变为 e。这可以通过调用数字上的 toString 方法来完成,该方法采用可选参数指定数字基数(例如,var number = 123; console.log(number.toString(16)); 将输出 7b)。

因此,我们可以得到一个随机的十六进制数字:

Math.floor(Math.random() * 16).toString(16)

所以让我们再次简化我们之前的代码,并改变这个...

var hexArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 'd', 'e', 'f'];
var rand = [];
for(var i = 0; i < 6; i++) {
    rand.push(hexArray[Math.floor(Math.random() * hexArray.length)]);
}

...为此:

var rand = [];
for(var i = 0; i < 6; i++) {
    rand.push(Math.floor(Math.random() * 16).toString(16));
}

所以整个代码现在看起来像这样:

var rand = [];
for(var i = 0; i < 6; i++) {
    rand.push(Math.floor(Math.random() * 16).toString(16));
}
var value = "#" + rand.join("");

//ignore this
$(document).ready(function() {
  $("body").css("background-color", value);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

但是嘿,我们还没有完成!


第 3 部分:

让我们回顾一下代码目前的作用:

  1. 它创建一个数组。
  2. 它将6个随机的十六进制数字压入数组。
  3. 它加入数组并在前面添加一个 #,以创建一个 CSS 颜色值。
  4. 设置CSS的背景色。

现在第 1-3 点可以进一步简化,因为最后,我们基本上是在创建一个 随机 6 位十六进制值 !

在第 2 步中,我们开始使用 Math.random(Math.floor() * 16).toString(16) 创建一个介于 0 和 16(不包括)之间的随机值,并将其转换为十六进制表示形式。为清楚起见,让我将此处的第一个 16 也更改为十六进制(如果您不知道,可以通过在它们前面加上前缀 0x 来使用十六进制文字):

Math.random(Math.floor() * 0x10).toString(16)

我们可以使用相同的机制创建一个介于 0 和 0xFFFFFF(含)之间的随机值,即 0 和 0x1000000(不含),如下所示:

Math.random(Math.floor() * 0x1000000).toString(16)

这将为我们提供随机值,例如 0x29F3D5(十进制 2749397)、0xC720FE(十进制 13050110)等

这听起来正是我们所需要的,对吧?嗯,差不多。随机值可能小于 0x100000,在这种情况下它们将少于 6 位数字,例如0xE81C 或 0x12345!

这意味着我们必须在左边用零填充它,以始终恰好有 6 位数字,不少于此。不幸的是,没有优雅的内置方法可以做到这一点,因此如果需要,我们必须手动添加零。因此,当随机函数为我们提供字符串 E81C 时,我们必须添加两个零才能使其成为 00E81C.

当然我们可以计算现有字符串的长度并计算 6 - length 然后添加那么多零...但是有一种更简单的方法可以做到这一点。因为我们知道我们总是至少有一位数字,最多为 6,而我们总是想要 6,这意味着我们必须根据现有长度添加 0 到 5 个零。我们现在可以假设最坏的情况 总是添加 5 个零:

"00000" + Math.floor(Math.random() * 0x1000000).toString(16)

当然这意味着字符串现在经常太长(6 到 11 个字符之间),但我们可以通过仅使用最后 6 个字符来解决这个问题,这可以使用字符串方法 substr.由于准确解释调用 substr 的不同方式会使这个已经很长的答案 太长 ,我将 link 到 the documentation for this method进一步阅读并告诉您可以使用负值作为参数从右边提取一定数量的字符。例如,"hello".substr(-3)" 会给你 llo.

所以,知道了这一点,我们就可以再次生成始终为我们提供 6 个随机十六进制数字的代码:

("00000" + Math.floor(Math.random() * 0x1000000).toString(16)).substr(-6)

请注意,我必须在 .substr 之前添加括号,否则 substr 方法只会在 + 右边的部分被调用,而不是整个事情。

让我们将这种新方法付诸实践。我们可以替换整个 rand 数组和 rand.join("") 部分。代码现在看起来像这样:

var value = "#" + ("00000" + Math.floor(Math.random() * 0x1000000).toString(16)).substr(-6);

//ignore this
$(document).ready(function() {
  $("body").css("background-color", value);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

这就是我们到达 the code suggested by Niet the Dark Absol in the comments 的方式!

2020 年更新: 如今,substr 技巧已不再需要,因为 padStart 已成为标准。所以,我们可以改用 "#" + Math.floor(Math.random() * 0x1000000).toString(16).padStart(6, '0').


我知道这是一个非常冗长的答案,也许您已经知道其中的大部分内容,但也许还不知道。也许您或其他人 reader 摸不着头脑我们是如何得出这个结果的,或者可能还有哪些其他优化步骤。这就是我编写此演练的原因。 :)

这对我来说是最简单的。一行,简单。

var randomColor = "#" + Math.floor(Math.random() * parseInt(0x1000000)).toString(16);