一、十六進制轉RGB
function hexToRgba(hex) {// 移除 # 字符hex = hex.replace('#', '');// 處理簡寫形式如 #fffif (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%):
- 所有顏色均為純黑(無論色相和飽和度如何)。
- 所有顏色均為純黑(無論色相和飽和度如何)。
- 頂部(L=100%):
(四)、什么是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 平面 → 紅綠混合色(如黃、紅、綠)。
歸一化如下圖
- 單通道為 0 的平面:
(七)、十六進制轉HSL
function hexToHsl(hex) {// 1. 去除#號并解析R,G,Blet 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)。
- 純紅色 (1,0,0):
數學推導
簡化公式為
和色度一樣,使用(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。
- 例如:在 0°~60°(紅→黃)區間:
插值系數的波形
- 波形形狀:
插值系數通過 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,顏色為橙色。
- 示例:當 H=30°(0°~60°區間):
計算明度偏移量
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的區別
模型 | 定義公式 | 幾何意義 | 示例(純紅色) | 適用場景 | 核心優勢 |
---|---|---|---|---|---|
HSV | V=max(R,G,B) | 顏色的最大亮度(最亮時顏色保持純色) | V=100% → 純紅(RGB: 255,0,0) | 圖像處理、快速調色 | 直觀調整顏色亮度 |
HSL | L= (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=100%):顏色保持最大亮度,但可能因 S 不同呈現不同鮮艷度。
- 顏色過渡規律
- 垂直方向(調整 V):
- 顏色亮度線性變化,但飽和度不變。
- 示例:V 從 50%→100%,顏色從暗紅→亮紅,但始終為紅色(H 固定)。
- 徑向方向(調整 S):
- 顏色從中心灰色逐漸變為邊緣純色。
- 示例:S 從 0%→100%,顏色從灰→淺紅→純紅。
- 圓周方向(調整 H):
- 顏色種類周期性變化,色輪角度對應不同顏色類型。
- 示例:H 從 0°→60°,顏色從紅→橙→黃。
- 垂直方向(調整 V):
(五)、十六進制轉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~1v = 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)。
參考文章
- 由RGB到HSV的轉換詳解
- 13 個 顏色轉換 的高級方法🌈
- 3D空間點到直線的距離
- 漫步色彩空間:解鎖HSV(HSB)的奧秘