马黑黑 发表于 2026-3-11 18:11

生成可控范围16进制随机颜色

<style>
        .artBox { font: normal 18px/1.2 sans-serif; overflow: auto; position: relative; }
        .artBox p { margin: 10px 0; }
        .artBox h1, .artBox h2 { margin: 4px 0; }
        .artBox code, .artBox pre { background: rgba(0,128,128,.25); padding: 2px 6px; tab-size: 4; }
        .artBox pre { padding: 10px 20px; white-space: pre-wrap; word-wrap: break-word; }
        .artBox pre code { padding: 0; background: none; }
        .artBox blockquote { margin: 10px 20px; padding: 2px 15px; border-left: 3px solid skyblue; background: rgba(240,248,255,.65); }
        .artBox table { border-collapse: collapse; white-space: pre-wrap; box-sizing: border-box; }
        .artBox th, .artBox td { padding: 8px 10px; border: 1px solid #999; }
        .artBox th { text-align: center; background: #eee; }
        .tMid { text-align: center; }
        .artBox iframe { width: 500px; height: 300px; border: none; outline: none; }
</style>

<div class="artBox">
<p>JS 生成16进制随机颜色可以非常简单,就一句代码:</p>
<pre><code>const color = '#' + Math.random().toString(16).substring(2, 8);
console.log(color); // → 类似结果:#33ed1f</code></pre>
<p>但当需要可控范围的16进制随机颜色,上述方法无能为力。要实现此功能——</p>
<p><strong>首先</strong>,需要理解16进制颜色的内部结构。本质上,16进制颜色由 R、G、B 即红、蓝、绿三种颜色按一定比例混合而成,每一种单色用16进制两位数表示,不足两位数的前面补零。完整的16进制颜色的表达方式如下:</p>
<blockquote>
<p><strong>#a6cc9f</strong></p>
<p>其中:</p>
<p><code>#</code> 是用来表示16进制的前缀;</p>
<p><code>a6</code> 是 R(红)、<code>cc</code> 是 G(绿)、<code>9f</code> 是B(蓝)</p>
</blockquote>
<p><strong>其次</strong>,需要了解单色分量取值范围,<code>0~255</code>,包含头尾数值。</p>
<p>下面是实现方法:</p>
<p>(一)设计一个取范围值函数,允许设定单色值范围:</p>
<pre><code>const getRdNumFromAr = (ar = ) =&gt; {
    ar.sort((a, b) =&gt; b &gt; a);
    const n1 = Math.min(Math.max(ar, 0), 255), n2 = Math.min(Math.max(ar, 0), 255);
    return Math.round(Math.random() * (n2 - n1) + n1);
};
</code></pre>
<p>此函数预设了取值范围为 ,没有传参时使用它。函数内部,先排序传参数组,以确保小数在前、大数在后;接着处理数组里面两个数值元素,用 Math.min 和 Math.max 方法确保数值不越界(0~255);最后,用 Math.random() 和 Math.round 方法取得最两个数值之间的随机数、四舍五入,并返回结果给调用者。</p>
<p>(二)设计一个创建16进制颜色的函数,允许配置 RGB 范围:</p>
<pre><code>const rdHexColor = (option) =&gt; {
    if (!option) option = { r: , g: , b: };
    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}`;
};
</code></pre>
<p>函数首先检测是否有传参,如果没有,创建 RGB 缺省配置;接着分别处理三种单色值,以红色 r 为例加以说明:调用 getRdNumFromAr() 函数处理配置值 r(<code>getRdNumFromAr(option.r)</code>),将其变为16进制(<code>toString(16)</code> 方法),得到的结果如果不足两位的前面补零(<code>patStart()</code> 方法);最后拼凑字串并返回结果。</p>
<p>完整的示例代码:</p>
<pre><code id="hexCode">&lt;style&gt;
    #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; }
&lt;/style&gt;

&lt;div id="myDiv" data-c="点击下方矩形生成随机颜色"&gt;&lt;/div&gt;

&lt;script&gt;
    const rdHexColor = (option) =&gt; {
      if (!option) option = { r: , g: , b: };
      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 = ) =&gt; {
      ar.sort((a, b) =&gt; b &gt; a);
      const n1 = Math.min(Math.max(ar, 0), 255), n2 = Math.min(Math.max(ar, 0), 255);
      return Math.round(Math.random() * (n2 - n1) + n1);
    };

    const setting = {
      r: ,
      g: ,
      b:
    };

    myDiv.onclick = () =&gt; myDiv.style.background = myDiv.dataset.c = rdHexColor(setting);
&lt;/script&gt;
</code></pre>
<p>效果如下:</p>
<div id="showDiv" class="tMid"></div>
<p>修改红蓝绿单色分量配置即 setting 对象,就可以拿到预期的颜色范围。</p>
</div>

<script>
        const preView = (htmlCode, targetBox) => {
                if (targetBox.innerHTML) return;
                const iframe = document.createElement('iframe');
                iframe.srcdoc = htmlCode;
                targetBox.appendChild(iframe);
                targetBox.style.display = 'block';
                targetBox.onclick = () => {
                        targetBox.innerHTML = '';
                        targetBox.style.display = 'none';
                }
        };
       
        preView(hexCode.innerText, showDiv);
</script>

杨帆 发表于 2026-3-11 18:49

很实用的知识,谢谢马老师经典讲授{:4_180:}

马黑黑 发表于 2026-3-11 19:52

杨帆 发表于 2026-3-11 18:49
很实用的知识,谢谢马老师经典讲授

这个应用场景还是很广的

杨帆 发表于 2026-3-11 20:03

马黑黑 发表于 2026-3-11 19:52
这个应用场景还是很广的

是啊,五彩缤纷的世界心之所向,只是运用自如并不容易呢{:4_180:}

马黑黑 发表于 2026-3-11 20:29

杨帆 发表于 2026-3-11 20:03
是啊,五彩缤纷的世界心之所向,只是运用自如并不容易呢

投入就有收获

杨帆 发表于 2026-3-11 22:50

马黑黑 发表于 2026-3-11 20:29
投入就有收获

至理名言,投入与收获在一起,感恩老师的讲授与指导{:4_180:}

红影 发表于 2026-3-11 23:34

这个例子是拿掉了红色,绿色蓝色也被设定在一定的范围里,即使这样,颜色其实仍然还是很多呢{:4_187:}

马黑黑 发表于 2026-3-13 12:23

红影 发表于 2026-3-11 23:34
这个例子是拿掉了红色,绿色蓝色也被设定在一定的范围里,即使这样,颜色其实仍然还是很多呢

你能看出 setting 配置的含义,太棒了

马黑黑 发表于 2026-3-13 12:23

杨帆 发表于 2026-3-11 22:50
至理名言,投入与收获在一起,感恩老师的讲授与指导

{:4_191:}

红影 发表于 2026-3-15 22:25

马黑黑 发表于 2026-3-13 12:23
你能看出 setting 配置的含义,太棒了

这是在黑黑的讲解里学习的,感谢黑黑夸奖,开心{:4_205:}

马黑黑 发表于 2026-3-16 13:45

红影 发表于 2026-3-15 22:25
这是在黑黑的讲解里学习的,感谢黑黑夸奖,开心

{:4_191:}

红影 发表于 2026-3-18 11:35

马黑黑 发表于 2026-3-16 13:45


干杯{:4_191:}

马黑黑 发表于 2026-3-18 14:36

红影 发表于 2026-3-18 11:35
干杯

谢干
页: [1]
查看完整版本: 生成可控范围16进制随机颜色