JS 生成16进制随机颜色可以非常简单,就一句代码:
const color = '#' + Math.random().toString(16).substring(2, 8);
console.log(color); // → 类似结果:#33ed1f
但当需要可控范围的16进制随机颜色,上述方法无能为力。要实现此功能——
首先,需要理解16进制颜色的内部结构。本质上,16进制颜色由 R、G、B 即红、蓝、绿三种颜色按一定比例混合而成,每一种单色用16进制两位数表示,不足两位数的前面补零。完整的16进制颜色的表达方式如下:
#a6cc9f
其中:
# 是用来表示16进制的前缀;
a6 是 R(红)、cc 是 G(绿)、9f 是B(蓝)
其次,需要了解单色分量取值范围,0~255,包含头尾数值。
下面是实现方法:
(一)设计一个取范围值函数,允许设定单色值范围:
const getRdNumFromAr = (ar = [0,255]) => {
ar.sort((a, b) => b > a);
const n1 = Math.min(Math.max(ar[0], 0), 255), n2 = Math.min(Math.max(ar[1], 0), 255);
return Math.round(Math.random() * (n2 - n1) + n1);
};
此函数预设了取值范围为 [0,255],没有传参时使用它。函数内部,先排序传参数组,以确保小数在前、大数在后;接着处理数组里面两个数值元素,用 Math.min 和 Math.max 方法确保数值不越界(0~255);最后,用 Math.random() 和 Math.round 方法取得最两个数值之间的随机数、四舍五入,并返回结果给调用者。
(二)设计一个创建16进制颜色的函数,允许配置 RGB 范围:
const rdHexColor = (option) => {
if (!option) option = { r: [0,255], g: [0,255], b: [0,255] };
const r = getRdNumFromAr(option.r).toString(16).padStart(2, '0');
const g = getRdNumFromAr(option.g).toString(16).padStart(2, '0');
const b = getRdNumFromAr(option.b).toString(16).padStart(2, '0');
return `#${r}${g}${b}`;
};
函数首先检测是否有传参,如果没有,创建 RGB 缺省配置;接着分别处理三种单色值,以红色 r 为例加以说明:调用 getRdNumFromAr() 函数处理配置值 r(getRdNumFromAr(option.r)),将其变为16进制(toString(16) 方法),得到的结果如果不足两位的前面补零(patStart() 方法);最后拼凑字串并返回结果。
完整的示例代码:
<style>
#myDiv { margin: auto; margin-top: 40px; width: 400px; height: 240px; border: 1px solid gray; position: relative; }
#myDiv::before { position: absolute; content: attr(data-c); top: -40px; }
</style>
<div id="myDiv" data-c="点击下方矩形生成随机颜色"></div>
<script>
const rdHexColor = (option) => {
if (!option) option = { r: [0,255], g: [0,255], b: [0,255] };
const r = getRdNumFromAr(option.r).toString(16).padStart(2, '0');
const g = getRdNumFromAr(option.g).toString(16).padStart(2, '0');
const b = getRdNumFromAr(option.b).toString(16).padStart(2, '0');
return `#${r}${g}${b}`;
};
const getRdNumFromAr = (ar = [0,255]) => {
ar.sort((a, b) => b > a);
const n1 = Math.min(Math.max(ar[0], 0), 255), n2 = Math.min(Math.max(ar[1], 0), 255);
return Math.round(Math.random() * (n2 - n1) + n1);
};
const setting = {
r: [0,0],
g: [30,200],
b: [30,200]
};
myDiv.onclick = () => myDiv.style.background = myDiv.dataset.c = rdHexColor(setting);
</script>
效果如下:
修改红蓝绿单色分量配置即 setting 对象,就可以拿到预期的颜色范围。