搜索
热搜: 活动 交友 discuz
查看: 6|回复: 1

马黑黑老师《生成可控范围16进制随机颜色》

[复制链接]
  • TA的每日心情
    开心
    昨天 21:09
  • 签到天数: 355 天

    连续签到: 17 天

    [LV.8]以坛为家I

    403

    主题

    1089

    回帖

    1万

    积分

    社区管理员

    积分
    12076

    最佳新人活跃会员热心会员推广达人宣传达人灌水之王突出贡献优秀版主荣誉管理

    发表于 昨天 21:23 | 显示全部楼层 |阅读模式

    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 对象,就可以拿到预期的颜色范围。

  • TA的每日心情
    奋斗
    昨天 13:51
  • 签到天数: 427 天

    连续签到: 17 天

    [LV.9]以坛为家II

    170

    主题

    708

    回帖

    1万

    积分

    社区贵宾

    积分
    11205

    最佳新人活跃会员热心会员推广达人宣传达人灌水之王突出贡献

    发表于 昨天 23:35 | 显示全部楼层
    很实用的知识,谢谢精彩分享
    该会员没有填写今日想说内容.
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|Archiver|小黑屋|纳兰音画网 ( 蜀ICP备2021011087号 )

    GMT+8, 2026-3-12 05:03 , Processed in 0.099152 second(s), 23 queries .

    Powered by Discuz! X3.5

    © 2001-2020 Comsenz Inc.

    快速回复 返回顶部 返回列表