当前位置: 首页 > news >正文

js 颜色转换分析

一、十六进制转RGB

  function hexToRgba(hex) {
    // 移除 # 字符
    hex = hex.replace('#', '');
    
    // 处理简写形式如 #fff
    if (hex.length === 3) {
        hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
    }
    
    // 转换为十进制
    const r = parseInt(hex.substring(0, 2), 16); // 截图前两位,然后16进制转为10进制
    const g = parseInt(hex.substring(2, 4), 16);
    const b = parseInt(hex.substring(4, 6), 16);
    
    return `rgb(${r}, ${g}, ${b})`;
  }
  • 使用十六进制表示颜色时,每两位代表一个颜色通道(#RRGGBB:RR=红,GG=绿,BB=蓝),范围00-FF(十进制0-255)。

二、RGB转十六进制

function rgbToHex(rgbStr) {
   // 提取 RGB 值
   const match = rgbStr.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)$/i);
   if (!match) {
       throw new Error('Invalid RGB/RGBA string format');
   }
   
   // 解析颜色分量
   const r = parseInt(match[1]);
   const g = parseInt(match[2]);
   const b = parseInt(match[3]);
   
   // 转换为十六进制
   const toHex = (num) => {
       const hex = Math.min(255, Math.max(0, num)).toString(16);
       return hex.length === 1 ? '0' + hex : hex;
   };
   
   return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
}
  • 使用正则表达式匹配rgb/rgba
    /^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)$/i // (?:,\s*([\d.]+))?:可选捕获透明度部分
    
  • 数值范围处理和十六进制转换
    const toHex = (num) => {
         // 1. 确保颜色值在 0-255 范围内
         // 2. 处理可能的非法输入值
         // 3. 转为十六进制
       const hex = Math.min(255, Math.max(0, num)).toString(16);
       return hex.length === 1 ? '0' + hex : hex;
    };
    

三、十六进制转HSL

(一)、什么是HSL

HSL(Hue, Saturation, Lightness)是一种基于人类感知的颜色表示方法,广泛应用于计算机图形学、网页设计和图像处理等领域。它比传统的 RGB(红绿蓝)模型更直观,便于调整颜色的色调、鲜艳度和明暗。

(二)、HSL中H、S、L分别代表什么

H:色相(Hue, H)

  • 定义:颜色的基本类型(如红、绿、蓝)。
  • 范围:0°–360°(环形色轮)。
    0° = 红色
    120° = 绿色
    240° = 蓝色
    360° = 回到红色
    在这里插入图片描述

色相和色度的区别

特性色相(Hue)色度(Chroma)
定义颜色的种类(红、绿、蓝等)颜色的纯度(鲜艳程度)
几何表示色轮上的角度(0°–360°)颜色点到灰度轴的距离
物理基础光的波长颜色成分的纯度(与灰度的偏离)
调整效果改变颜色类别(如红→蓝)改变颜色的鲜艳度(如鲜红→灰红)
感知独立性与明度、饱和度无关与明度相关(明度影响最大色度)

S:饱和度(Saturation, S)

  • 定义:颜色的鲜艳程度(从灰度到纯色)。
  • 范围:0%–100%
    0% = 灰色(完全去色)
    100% = 最鲜艳的颜色
    在这里插入图片描述

L:明度(Lightness, L)

  • 定义:颜色的明暗程度(从黑到白)。
  • 范围:0%–100%
    0% = 纯黑
    50% = 标准颜色
    100% = 纯白

(三)、HSL的圆柱模型

HSL还有双六棱锥模型,这里主要说圆柱模型
HSL(色相、饱和度、明度)的圆柱模型是一种直观的几何表示方式,将颜色的三个属性映射到三维空间中。

基本结构

  • 色相(Hue, H)
    • 几何位置:围绕圆柱的圆周方向(0°–360°)。
    • 物理意义:颜色在色轮上的角度,决定颜色种类(如红、绿、蓝)。
  • 饱和度(Saturation, S)
    • 几何位置:从圆柱中心到边缘的径向距离(0%–100%)。
    • 物理意义:颜色的鲜艳程度,中心为灰色,边缘为纯色。
  • 明度(Lightness, L)
    • 几何位置:沿圆柱的垂直轴高度(0%–100%)。
    • 物理意义:颜色的明暗程度,底部为纯黑,顶部为纯白,中间为纯色。

关键几何特征

  • 灰度轴(中心轴)
    • 位置:圆柱的中心垂直线(S=0%)。
  • 颜色特性:
    • 所有点均为灰色,色相(H)无意义。
    • 明度(L)决定灰度深浅:
      • L=0% → 纯黑
      • L=100% → 纯白
      • L=50% → 中性灰
  • 中间平面(L=50%)
    • 位置:圆柱的中间水平截面(高度为 50%)。
    • 颜色特性:
      • 所有颜色处于最鲜艳状态(饱和度 S=100%)。
      • 色相(H)在此平面上形成完整的 色相环(红→黄→绿→青→蓝→品红→红)。
  • 顶部与底部
    • 顶部(L=100%):
      • 所有颜色均为纯白(无论色相和饱和度如何)。
    • 底部(L=0%):
      • 所有颜色均为纯黑(无论色相和饱和度如何)。
        在这里插入图片描述

(四)、什么是RGB

RGB(Red, Green, Blue)是一种基于光学的颜色表示方法,通过红、绿、蓝三原色的不同比例混合来定义颜色。它是数字设备(如显示器、摄像头)最基础的颜色模型。

(五)、RGB中R、G、B分别代表什么

R:(Red,红色)

  • 定义:红色光的强度,是光的三原色之一。
  • 作用:红色分量主导颜色中的红色成分。
  • 示例:纯红色的 RGB 值为 (255, 0, 0)。

G(Green,绿色)

  • 定义:绿色光的强度,是光的三原色之一。
  • 作用:绿色分量主导颜色中的绿色成分。
  • 示例:纯绿色的 RGB 值为 (0, 255, 0)。

B(Blue,蓝色)

  • 定义:蓝色光的强度,是光的三原色之一。
  • 作用:蓝色分量主导颜色中的蓝色成分。
  • 示例:纯蓝色的 RGB 值为 (0, 0, 255)。

(六)RGB的立方体模型

RGB 立方体模型是描述 RGB 颜色空间最直观的几何表示方式。它通过三维坐标系将红(R)、绿(G)、蓝(B)三个颜色分量的组合关系可视化,帮助理解颜色的混合规律和分布特性。

基本结构
RGB 立方体是一个三维直角坐标系:

  • 三个坐标轴:

    • R 轴(红色):从左(0)到右(255 或 1.0)
    • G 轴(绿色):从前(0)到后(255 或 1.0)
    • B 轴(蓝色):从下(0)到上(255 或 1.0)
  • 顶点:立方体的 8 个顶点对应极端颜色值,例如:

    • (0,0,0) → 纯黑色
    • (255,255,255) → 纯白色
    • (255,0,0) → 纯红色
    • (0,255,0) → 纯绿色
    • (0,0,255) → 纯蓝色

关键几何特征

  • 灰度对角线

    • 定义:从黑色 (0,0,0) 到白色 (255,255,255) 的对角线。
    • 颜色特性:线上所有点满足 R=G=B,即 灰度色。
      • 例如:(128,128,128) → 中灰色。
  • 纯色顶点

    • 6 个非黑白顶点:对应红、绿、蓝及其两两混合的纯色:

      顶点坐标颜色名称
      (255,0,0)纯红
      (0,255,0)纯绿
      (0,0,255)纯蓝
      (255,255,0)黄(红+绿)
      (255,0,255)品红(红+蓝)
      (0,255,255)青(绿+蓝)
  • 颜色平面

    • 单通道为 0 的平面:
      • R=0 平面 → 蓝绿混合色(如青、蓝、绿)。
      • G=0 平面 → 红蓝混合色(如品红、红、蓝)。
      • B=0 平面 → 红绿混合色(如黄、红、绿)。
        在这里插入图片描述
        归一化如下图
        归一化

(七)、十六进制转HSL

function hexToHsl(hex) {
  // 1. 去除#号并解析R,G,B
  let r = parseInt(hex.slice(1, 3), 16) / 255;
  let g = parseInt(hex.slice(3, 5), 16) / 255;
  let b = parseInt(hex.slice(5, 7), 16) / 255;

  // 2. 计算最大值、最小值和色度(Chroma)
  let max = Math.max(r, g, b);
  let min = Math.min(r, g, b);
  let chroma = max - min;

  // 3. 计算明度(Lightness)
  let l = (max + min) / 2;

  // 4. 计算色相(Hue)和饱和度(Saturation)
  let h = 0, s = 0;
  
  if (chroma !== 0) {
    // 饱和度计算
    s = chroma / (1 - Math.abs(2 * l - 1));
    
    // 色相计算
    switch (max) {
      case r: h = ((g - b) / chroma) % 6; break;
      case g: h = (b - r) / chroma + 2; break;
      case b: h = (r - g) / chroma + 4; break;
    }
    h = h * 60;
    if (h < 0) h += 360; // 确保色相在0-360度之间
  }

  // 5. 返回HSL对象(色相四舍五入,饱和度和明度转为百分比)
  return {
    h: Math.round(h),
    s: Math.round(s * 100),
    l: Math.round(l * 100)
  };
}

使用max - min计算色度的几何意义

  let max = Math.max(r, g, b);
  let min = Math.min(r, g, b);
  let chroma = max - min;

色度表示颜色点 P(R,G,B) 到灰度轴的垂直距离,即颜色偏离灰色的程度。:

  • 当 C=0:颜色位于灰度轴上(完全无色彩)。
  • 当 C=1:颜色为纯色(如纯红、纯绿、纯蓝)。

总结:当某个分量(如R)远大于其他分量时,max - min 的值越大,颜色越接近纯色(如纯红)。

数学推导
颜色点到灰度轴的距离(三维空间中的垂直距离)为:
在这里插入图片描述
而 C=max−min 是该距离的简化近似,避免了复杂的平方根运算, 但是忽略了部分分量差异。会导致色度越大,颜色越偏离灰色。

根号3的来源,使用到了空间向量相关知识。公式如下
在这里插入图片描述

使用(max - min)/2计算色度的几何意义

 let l = (max + min) / 2;

明度表示颜色点在灰度轴上的投影位置。具体来说,颜色点 P(R,G,B)沿垂直于灰度轴的方向投影到灰度轴上,得到的投影点坐标为 (L,L,L)其中 L 是明度值。

  • 示例:
    • 纯红色 (1,0,0):
      L=(1+0)/2=0.5,投影点为 (0.5,0.5,0.5),即中等灰色。
    • 浅蓝色 (0.2,0.8,0.8):
      L= (0.8+0.2)/2 =0.5,投影点仍为 (0.5,0.5,0.5)。

数学推导
在这里插入图片描述
简化公式为
在这里插入图片描述
和色度一样,使用(max+min)/2 计算明度只需比较和一次加法,适合实时计算(如早期图形处理),同时还可以兼容HSL中饱和度的计算。

色度和明度对比

属性几何意义物理意义计算依赖
色度颜色到灰度轴的垂直距离颜色的纯度(偏离灰色的程度)max 和 min 的差值
明度颜色在灰度轴上的投影位置颜色的整体亮度(等效灰色亮度)max 和 min 的平均值

使用chroma / (1 - Math.abs(2 * l - 1))计算饱和度的几何意义

 s = chroma / (1 - Math.abs(2 * l - 1));

在这里插入图片描述
这相当于:

  • 在RGB立方体中,从当前颜色点向灰度轴作垂线
  • 计算该点到灰度轴的距离(实际色度)
  • 计算该明度平面上可能的最大色度
  • 求两者的比值

可视化理解:

  • 想象RGB立方体:
    • 在L=0.5的中间平面,最大色度大(分母大),容易得到高饱和度
    • 在L接近0或1的平面,最大色度小(分母小),饱和度被压缩
  • 这种设计确保了:
    • 纯色总是在L=0.5时S=100%
    • 接近黑白时饱和度自动降低

计算色相的几何意义

 switch (max) {
    case r: h = ((g - b) / chroma) % 6; break;
    case g: h = (b - r) / chroma + 2; break;
    case b: h = (r - g) / chroma + 4; break;
  }

为什么计算色相时需要分三段进行判断?

色相表示颜色在色轮上的位置(0°~360°),不同主色对应不同区间:

  • 红色(R):0°(或360°)
  • 绿色(G):120°
  • 蓝色(B):240°

色相的计算需要根据最大值通道确定基础角度,再通过其他通道的相对差异调整偏移量。

当最大值是R时

case r: h = ((g - b) / chroma) % 6; break; // 这里 % 6 是为了防止差值出超过0-6之间的数值。如果差值超过0-6的范围那么%6可以回到范围
  • 基础角度:0°(红色)
  • 偏移方向:
    • 若G > B → 向黄色(60°方向)偏移。
    • 若B > G → 向品红色(300°方向)偏移。
  • 计算公式:
    • 在这里插入图片描述
    • 几何意义:计算G和B的相对比例,归一化到[-1,1],再映射到0-6的临时值。

当最大值是G时

case g: h = (b - r) / chroma + 2; break;
  • 基础角度:120°(绿色)
  • 偏移方向:
    • 若B > R → 向青色(180°方向)偏移。
    • 若R > B → 向黄色(60°方向)偏移。
  • 计算公式:
    • 在这里插入图片描述
    • 几何意义:+2 将结果偏移到绿色区域(120°)。

当最大值是B时

  • 基础角度:240°(蓝色)
  • 偏移方向:
    • 若R > G → 向品红色(300°方向)偏移。
    • 若G > R → 向青色(180°方向)偏移。
  • 计算公式:
    • 在这里插入图片描述
    • 几何意义:+4 将结果偏移到蓝色区域(240°)

为什么计算色相时当最大值为r时公式里面是g-b为不是b-g?

色轮以 逆时针方向 定义颜色过渡:
红色(0°) → 黄色(60°) → 绿色(120°) → 青色(180°) → 蓝色(240°) → 品红(300°) → 红色(360°)。
当 R为最大值 时:
若 G > B,颜色偏向 黄色(60°方向),此时 (G - B) 为正,色相应 增加。
若 B > G,颜色偏向 品红色(300°方向),此时 (G - B) 为负,色相应 减少。
使用 (G - B) 而非 (B - G) 能直接反映这一方向性。(同样道理适用于最大值为g或b)

四、HSL转十六进制

function hslToHex(h, s, l) {
  // 规范化输入值
  h = h % 360;
  s = Math.max(0, Math.min(100, s)) / 100;
  l = Math.max(0, Math.min(100, l)) / 100;

  // 处理灰度色
  if (s === 0) {
    const gray = Math.round(l * 255);
    return `#${gray.toString(16).padStart(2, '0').repeat(3)}`;
  }

  // 计算色度、中间值和明度偏移
  const c = (1 - Math.abs(2 * l - 1)) * s;
  const x = c * (1 - Math.abs((h / 60) % 2 - 1));
  const m = l - c / 2;

  // 根据色相确定RGB初始值
  let r, g, b;
  if (h >= 0 && h < 60) {
    [r, g, b] = [c, x, 0];
  } else if (h < 120) {
    [r, g, b] = [x, c, 0];
  } else if (h < 180) {
    [r, g, b] = [0, c, x];
  } else if (h < 240) {
    [r, g, b] = [0, x, c];
  } else if (h < 300) {
    [r, g, b] = [x, 0, c];
  } else {
    [r, g, b] = [c, 0, x];
  }

  // 转换为十六进制
  const toHex = (value) => {
    const hex = Math.round((value + m) * 255).toString(16);
    return hex.padStart(2, '0');
  };

  return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
}

获取色度

const c = (1 - Math.abs(2 * l - 1)) * s;

是上面十六进制转为HSL中饱和度s=chroma / (1 - Math.abs(2 * l - 1)); 再乘以(1 - Math.abs(2 * l - 1))得到色度

计算中间颜色分量的值

const x = c * (1 - Math.abs((h / 60) % 2 - 1));

分步理解公式

  • 色相分段:h / 60
    • 将色相 H 按每 60° 分段,对应色轮上的 6 个主色区间(红、黄、绿、青、蓝、品红)。
  • 模2操作:(h / 60) % 2
    • 将分段后的色相值映射到 0~2 的范围内,用于在每段内生成对称的插值系数。
  • 归一化到 -1~1:(h / 60) % 2 - 1
    • 通过减去 1,将范围调整为 -1~1,便于后续的绝对值处理。
  • 生成插值系数:1 - Math.abs(…)
    • 取绝对值后,值域为 0~1,再用 1 减去它,得到 0→1→0 的三角形波形,用于颜色分量的平滑过渡。
  • 乘以色度 C:c * …
    • 最终结果表示中间颜色分量的强度,范围在 0~C 之间。

为什么乘以色度?

  • 色度 C 表示颜色的纯度,插值系数与 C 相乘,确保颜色强度与饱和度一致。
    • 高饱和度( 最大,颜色鲜艳)。
    • 低饱和度(颜色为灰色)。

中间颜色分量的几何意义:

色相分段与颜色过渡

  • 每 60° 对应一个颜色区间:
    • 0°~60°:红色 → 黄色
    • 60°~120°:黄色 → 绿色
    • 120°~180°:绿色 → 青色
    • 180°~240°:青色 → 蓝色
    • 240°~300°:蓝色 → 品红
    • 300°~360°:品红 → 红色
  • 中间分量的作用:
    在每个区间内,一个颜色分量保持最大值(由主色决定),另一个分量从 0 增长到最大值(或从最大值减少到 0),第三个分量保持为 0。
    • 例如:在 0°~60°(红→黄)区间:
      • 红色分量 R=C(最大)
      • 绿色分量 G=C×插值系数(从 0 到 C)
      • 蓝色分量 B=0。

插值系数的波形

  • 波形形状:
    插值系数通过 1 - Math.abs((h / 60) % 2 - 1) 生成 三角形波形,在每 60° 区间内从 0 线性增长到 1,再线性减少到 0。
    • 示例:当 H=30°(0°~60°区间):
      插值系数=1−∣(30/60)%2−1∣=1−∣0.5−1∣=0.5
      此时绿色分量 G=C×0.5,颜色为橙色。

计算明度偏移量

const m = l - c / 2;

计算明度偏移量的几何意义

平移中间分量:将中间分量(如 r′,g′,b ′)从相对范围 0∼C 平移到实际范围 L− C/2∼L+ C/2,保颜色在灰度轴上的投影亮度为 L。

计算明度偏移量的数据推导

HSL明度的定义:

  • 在HSL模型中,明度 L 是RGB分量的最大值(max)和最小值(min)的算术平均值
    • 在这里插入图片描述

色度 C 的定义:

  • 色度(Chroma) 表示颜色的纯度,即RGB分量的最大值与最小值之差:
    • 在这里插入图片描述

联立方程求解

  • 通过联立上述两个方程,可以推导出 min 和 max:
    • 在这里插入图片描述
    • max:颜色分量的最大值(例如纯红色时 R=1)
    • min:颜色分量的最小值(例如纯红色时 G=B=0)

明度偏移量 m 的引入
在HSL转RGB时,中间分量(如 r ′,g ′,b ′)是基于色相和饱和度计算出的相对值(范围0~C)。为了将这些中间分量映射到实际RGB值(范围0~1),需要加上一个偏移量 m,使得:
在这里插入图片描述
将 m=L− C/2代入,可保证:
在这里插入图片描述
从而满足HSL明度的定义。

根据色相区间确定 RGB 初始值

  let r, g, b;
  if (h >= 0 && h < 60) {
    [r, g, b] = [c, x, 0];
  } else if (h < 120) {
    [r, g, b] = [x, c, 0];
  } else if (h < 180) {
    [r, g, b] = [0, c, x];
  } else if (h < 240) {
    [r, g, b] = [0, x, c];
  } else if (h < 300) {
    [r, g, b] = [x, 0, c];
  } else {
    [r, g, b] = [c, 0, x];
  }
色相区间临时 RGB 值
0°-60°(C, X, 0)
60°-120°(X, C, 0)
120°-180°(0, C, X)
180°-240°(0, X, C)
240°-300°(X, 0, C)
300°-360°(C, 0, X)

调整 RGB 值并转换为十六进制

 const toHex = (value) => {
    const hex = Math.round((value + m) * 255).toString(16);
    return hex.padStart(2, '0');
  };
  • 将 RGB 值加上明度偏移量 m,并限制在 0-1 范围内。
  • 转换为 0-255 的整数,再转为两位十六进制。

五、十六进制转HSV

虽然HSV和HSL看着名字相似,但它们的定义和计算逻辑有本质区别。尽管在十六进制→HSL 和 十六进制→HSV(HSV → 十六进制 和 HSL → 十六进制) 的转换过程中,计算中间值(如色度 c 和辅助变量 x)或者色度等公式看起来相似,但它们的物理含义不同,最终转换结果也不同

(一)、什么是HSV

HSV(Hue, Saturation, Value)是一种基于人类颜色感知的模型,用于直观描述颜色的 色调、鲜艳度 和 亮度。它在图像处理、设计工具和数据可视化中广泛应用。

(二)、HSV中H、S、V分别代表什么

H:色相(Hue, H)

  • 定义:颜色的基本类型(如红、绿、蓝)。
  • 范围:0°–360°(环形色轮)。
    0° = 红色
    120° = 绿色
    240° = 蓝色
    360° = 回到红色

S:饱和度(Saturation, S)

  • 定义:颜色的鲜艳程度(从灰度到纯色)。
  • 范围:0%–100%
    0% = 灰色(完全去色)
    100% = 最鲜艳的颜色

V:明度(Value,V)

  • 定义:颜色的亮度。明度越高,颜色越亮;越低则越暗。
  • 范围:0%(纯黑)–100%(最亮,颜色保持纯色)。
    V=100%:亮红色(RGB的红色通道全开)。
    V=50%:暗红色(亮度减半)。
    V=0%:纯黑色(所有颜色通道关闭)。

(三)、HSV和HSL的区别

模型定义公式几何意义示例(纯红色)适用场景核心优势
HSVV=max(R,G,B)颜色的最大亮度(最亮时颜色保持纯色)V=100% → 纯红(RGB: 255,0,0)图像处理、快速调色直观调整颜色亮度
HSLL= (max+min)/2颜色的平均亮度(中等亮度时颜色最纯)L=50% → 纯红(RGB: 255,0,0)设计、数据可视化自然保持颜色鲜艳度

(四)、HSV的圆柱模型

HSV还有单六棱锥模型,这里主要说圆柱模型

基本结构

HSV 圆柱模型由三个正交维度构成,分别对应色相(H)、饱和度(S)、明度(V):

  • 色相(Hue)

    • 几何方向:沿圆柱的 圆周分布,角度范围为 0°–360°。
    • 物理意义:决定颜色的基本类型(如红、绿、蓝等)。
  • 饱和度(Saturation)

    • 几何方向:沿圆柱的 径向分布,范围 0%(中心)–100%(边缘)。
    • 物理意义:表示颜色纯度(鲜艳程度)。
  • 明度(Value)

    • 几何方向:沿圆柱的 垂直轴分布,范围 0%(底部)–100%(顶部)。
    • 物理意义:控制颜色亮度(明暗程度)。

关键几何特征

  • 色相环的连续性
    • 圆周闭合性:色相角度 0° 与 360° 重合,颜色从红→黄→绿→青→蓝→品红→红无缝过渡。
    • 几何意义:圆柱的圆周方向形成闭环,确保颜色过渡无间断。
  • 饱和度与径向距离
    • 中心轴为灰度轴:当 S=0% 时,无论 H 和 V 如何,颜色均为不同明度的灰色(如深灰、浅灰)。
    • 边缘为纯色:当 S=100% 时,颜色达到最大纯度,对应 RGB 的纯色(如红、绿、蓝)。
  • 底部为纯黑(V=0%):所有颜色在 V=0% 时均变为黑色,与 H 和 S 无关。
    • 顶部为最亮纯色(V=100%):颜色保持最大亮度,但可能因 S 不同呈现不同鲜艳度。
      • 示例:
        • V=100%、S=100% → 纯红色(RGB: 255,0,0)。
        • V=100%、S=50% → 浅红色(RGB: 255,128,128)。
  • 颜色过渡规律
    • 垂直方向(调整 V):
      • 颜色亮度线性变化,但饱和度不变。
      • 示例:V 从 50%→100%,颜色从暗红→亮红,但始终为红色(H 固定)。
    • 径向方向(调整 S):
      • 颜色从中心灰色逐渐变为边缘纯色。
      • 示例:S 从 0%→100%,颜色从灰→浅红→纯红。
    • 圆周方向(调整 H):
      • 颜色种类周期性变化,色轮角度对应不同颜色类型。
      • 示例:H 从 0°→60°,颜色从红→橙→黄。

在这里插入图片描述

(五)、十六进制转HSV

function hexToHsv(hex) {
  // 1. 移除#号并解析R, G, B分量(0~255)
  hex = hex.replace(/^#/, '');
  let r, g, b;
  if (hex.length === 3) {
    // 处理简写格式(如 #RGB → #RRGGBB)
    r = parseInt(hex[0] + hex[0], 16);
    g = parseInt(hex[1] + hex[1], 16);
    b = parseInt(hex[2] + hex[2], 16);
  } else {
    r = parseInt(hex.substring(0, 2), 16);
    g = parseInt(hex.substring(2, 4), 16);
    b = parseInt(hex.substring(4, 6), 16);
  }

  // 2. 归一化到0~1范围
  r /= 255, g /= 255, b /= 255;

  // 3. 计算最大值、最小值和色度(Chroma)
  const max = Math.max(r, g, b);
  const min = Math.min(r, g, b);
  const chroma = max - min;

  // 4. 计算明度(Value)
  const v = max;

  // 5. 计算饱和度(Saturation)
  let s = max === 0 ? 0 : chroma / max;

  // 6. 计算色相(Hue)
  let h = 0;
  if (chroma !== 0) {
    switch (max) {
      case r:
        h = ((g - b) / chroma) % 6;
        break;
      case g:
        h = (b - r) / chroma + 2;
        break;
      case b:
        h = (r - g) / chroma + 4;
        break;
    }
    h = (h * 60 + 360) % 360; // 确保角度在0~360之间
  }

  // 7. 转换为百分比并四舍五入
  return {
    h: Math.round(h),
    s: Math.round(s * 100),
    v: Math.round(v * 100)
  };
}

计算色度

  const chroma = max - min;

原理和HSL一样,不再赘诉

计算明度

   const v = max;

根据HSL模型定义,明度直接取最大值

计算饱和度

  let s = max === 0 ? 0 : chroma / max;

为什么在计算饱和度时HSV和HSL两个模型公式不一样?

这源于两者对颜色亮度的定义差异以及几何模型的根本区别

HSV/HSL中对S公式理解

  • HSV 的饱和度公式
    • 在这里插入图片描述
    • 物理意义:
      • 饱和度是 色度(Chroma)占当前明度(V)的比例。
      • 明度 V 是 RGB 的最大值,因此饱和度表示颜色纯度相对于最大亮度的占比。
        • 纯红色(RGB(255,0,0)):V=1,Chroma=1→S=100%。
        • 浅红色(RGB(255,128,128)):V=1,Chroma=0.5→S=50%。
  • HSL 的饱和度公式
    • 在这里插入图片描述
    • 物理意义:
      • 饱和度是 色度占当前亮度下可能的最大色度的比例。
      • 分母 1−∣2L−1∣ 表示当前亮度 L 下允许的最大色度。
        • 当 L=0.5(中等亮度)时,分母为 1,饱和度 S=Chroma
        • 当 L→0 或 L→1(接近黑/白)时,分母趋近 0,饱和度被压缩。

计算色相

 if (chroma !== 0) {
    switch (max) {
      case r:
        h = ((g - b) / chroma) % 6;
        break;
      case g:
        h = (b - r) / chroma + 2;
        break;
      case b:
        h = (r - g) / chroma + 4;
        break;
    }
    h = (h * 60 + 360) % 360; // 确保角度在0~360之间
  }

原理和HSL一样,不再赘诉

六、HSV转十六进制

function hsvToHex(h, s, v) {
  // 1. 规范化输入值
  h = ((h % 360) + 360) % 360; // 确保色相在0~360之间
  s = Math.max(0, Math.min(100, s)) / 100; // 饱和度转为0~1
  v = Math.max(0, Math.min(100, v)) / 100; // 明度转为0~1

  // 2. 处理饱和度为0的情况(灰度色)
  if (s === 0) {
    const gray = Math.round(v * 255);
    return `#${gray.toString(16).padStart(2, '0').repeat(3)}`;
  }

  // 3. 计算色度、中间值和明度偏移
  const c = v * s;
  const x = c * (1 - Math.abs(((h / 60) % 2) - 1));
  const m = v - c;

  // 4. 根据色相区间确定RGB初始值
  let r, g, b;
  if (h < 60) {
    [r, g, b] = [c, x, 0];
  } else if (h < 120) {
    [r, g, b] = [x, c, 0];
  } else if (h < 180) {
    [r, g, b] = [0, c, x];
  } else if (h < 240) {
    [r, g, b] = [0, x, c];
  } else if (h < 300) {
    [r, g, b] = [x, 0, c];
  } else {
    [r, g, b] = [c, 0, x];
  }

  // 5. 调整RGB值并转换为十六进制
  const toHex = (value) => {
    const hex = Math.round((value + m) * 255).toString(16);
    return hex.padStart(2, '0');
  };

  return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
}

计算色度

  const c = v * s;

在HSV中为什么计算色度公式是v * s?

色度 c 是颜色在 RGB 空间中的最大分量与最小分量的差值,表示颜色的“纯度”或“鲜艳程度”。在 HSV 模型中:

  • 当 S = 1 时,颜色为纯色,色度 c 达到最大值(c = V)。
  • 当 S = 0 时,颜色为灰色,色度 c = 0。
  • 因此,色度 c 是饱和度和明度的乘积:
    c = V * S

计算中间值

const x = c * (1 - Math.abs(((h / 60) % 2) - 1));

这里和上面HSL转十六进制时求x理解一致(这是因为在十六进制转为HSL和十六进制转为HSV转换中对色相的处理方式完全相同)

明度偏移

const m = v - c;

为什么HSL或HSV转为十六进制 m 的计算方式不同?

  • HSV

    • 在 RGB 中,max(R, G, B) = v(由 v 决定)
    • min(R, G, B) = v - c(因为 c = max - min)。
    • 所以 m 的作用是 确保 min(R, G, B) 正确,使得:
      • 当 s = 1 时,c = v,m = 0(纯色,最小值是 0)。
      • 当 s = 0 时,c = 0,m = v(灰度,所有分量等于 v)。
  • HSL

    • 在 RGB 中,(max + min) / 2 = l(由 l 决定)。
    • c = max - min(色度)。
    • 所以 min = l - c / 2(因为 max = min + c,代入 (max + min)/2 = l 可得)。
    • m 的作用是 确保 min(R, G, B) 正确,使得:
      • 当 s = 1 且 l = 0.5 时,c = 1,m = 0.5 - 0.5 = 0(纯色)。
      • 当 s = 0 时,c = 0,m = l(灰度,所有分量等于 l)。

参考文章

  1. 由RGB到HSV的转换详解
  2. 13 个 颜色转换 的高级方法🌈
  3. 3D空间点到直线的距离
  4. 漫步色彩空间:解锁HSV(HSB)的奥秘

相关文章:

  • 【Flink运行时架构】核心组件
  • 优化方法介绍(一)
  • PCIe 5.0光学SSD原型问世!
  • 2025-4-11 情绪周期视角复盘(mini)
  • java -jar与java -cp的区别
  • 操作系统 ------ 五种IO模型
  • 前端工程化-包管理NPM-package.json 和 package-lock.json 详解
  • 小甲鱼第004讲:变量和字符串(下)| 课后测试题及答案
  • Git基础知识
  • 蓝桥杯单片机刷题——ADC测量电位器的电压
  • 基于FPGA的六层电梯智能控制系统 矩阵键盘-数码管 上板仿真均验证通过
  • 深入解析Python爬虫技术:从基础到实战的功能工具开发指南
  • python文件打包无法导入ultralytics模块
  • 4月12日随笔
  • 【区块链安全 | 第三十九篇】合约审计之delegatecall(一)
  • 通信中的 “bps“ 含义及详解
  • linux小白对系统环境变量的一些不解和迷惑解析
  • Python(10.2)Python可变与不可变类型内存机制解密:从底层原理到工程实践
  • C 语言 - 右左法则与实践练习题 答案解析
  • 文档检索技术详解 (Document Retriever)
  • 淘宝网站优化实例/正规赚佣金的平台
  • 网站底部版权信息字体颜色/营销型网站建设团队
  • 优质的网站建设推广/百度推广优化公司
  • 开发板是干什么用的/广州做seo整站优化公司
  • 酒泉网站建设服务/什么是seo推广
  • 双语cms网站/惠州搜索引擎优化