前端颜色工具函数详解:从 HEX 到 HSL 的完整转换方案
前言
在前端开发中,颜色处理是一个常见且重要的需求。无论是构建颜色选择器、主题切换功能,还是实现动态配色方案,都需要对颜色进行各种格式的转换和处理。本文将深入解析一套完整的颜色工具函数库,涵盖 HEX、RGB、HSL 三种主流颜色格式之间的相互转换,以及对比色计算、色阶生成等实用功能。
RGB转十六进制 - 在线颜色代码转换工具 | 免费快速转换
目录
类型定义
在开始之前,我们先了解一下基础的类型定义:
interface RGB {
r: number; // 红色分量,范围 0-255
g: number; // 绿色分量,范围 0-255
b: number; // 蓝色分量,范围 0-255
}
interface HSL {
h: number; // 色相,范围 0-360
s: number; // 饱和度,范围 0-100
l: number; // 亮度,范围 0-100
}
HEX ↔ RGB 转换
1. hexToRgb:十六进制转 RGB
功能描述:将十六进制颜色值(如 #FF5733 或 FF5733)转换为 RGB 对象。
实现原理:
- 使用正则表达式
/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i匹配6位十六进制字符串 - 支持带
#号和不带#号的格式 - 将每个两位十六进制数解析为十进制(0-255)
代码实现:
export const hexToRgb = (hex: string): RGB | null => {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result ? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16)
} : null;
};
使用示例:
hexToRgb('#FF5733'); // { r: 255, g: 87, b: 51 }
hexToRgb('FF5733'); // { r: 255, g: 87, b: 51 }
hexToRgb('invalid'); // null
注意事项:
- 如果输入的十六进制格式不正确,函数返回
null - 正则表达式使用
i标志,支持大小写字母
2. rgbToHex:RGB 转十六进制
功能描述:将 RGB 三个分量转换为十六进制颜色字符串。
实现原理:
- 将每个 RGB 分量限制在 0-255 范围内
- 转换为十六进制字符串,不足两位时补零
- 组合成
#RRGGBB格式
代码实现:
export const rgbToHex = (r: number, g: number, b: number): string => {
const toHex = (c: number) => {
const hex = Math.max(0, Math.min(255, c)).toString(16);
return hex.length === 1 ? '0' + hex : hex;
};
return '#' + toHex(r) + toHex(g) + toHex(b);
};
使用示例:
rgbToHex(255, 87, 51); // '#ff5733'
rgbToHex(0, 0, 0); // '#000000'
rgbToHex(300, -10, 50); // '#ff0032' (自动限制范围)
关键点:
Math.max(0, Math.min(255, c))确保值在有效范围内- 使用
toString(16)进行进制转换 - 单数位时补零,保证输出格式统一
RGB ↔ HSL 转换
3. rgbToHsl:RGB 转 HSL
功能描述:将 RGB 颜色转换为 HSL(色相、饱和度、亮度)格式。
实现原理:
- 归一化:将 RGB 值从 0-255 范围归一化到 0-1
- 计算最大值和最小值:找出 RGB 中的最大值和最小值
- 计算亮度(Lightness):
L = (max + min) / 2 - 计算饱和度(Saturation):
- 如果
max === min,饱和度为 0(灰度色) - 否则根据亮度选择公式:
L > 0.5:S = d / (2 - max - min)L ≤ 0.5:S = d / (max + min)
- 如果
- 计算色相(Hue):
- 根据最大值所在的颜色分量计算
- 最终转换为 0-360 度范围
代码实现:
export const rgbToHsl = (r: number, g: number, b: number): HSL => {
r /= 255;
g /= 255;
b /= 255;
const max = Math.max(r, g, b), min = Math.min(r, g, b);
let h = 0, s, l = (max + min) / 2;
if (max === min) {
h = s = 0;
} else {
const d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
return {
h: Math.round(h * 360),
s: Math.round(s * 100),
l: Math.round(l * 100)
};
};
使用示例:
rgbToHsl(255, 87, 51); // { h: 11, s: 100, l: 60 }
rgbToHsl(255, 255, 255); // { h: 0, s: 0, l: 100 } (白色)
rgbToHsl(0, 0, 0); // { h: 0, s: 0, l: 0 } (黑色)
算法详解:
- HSL 模型更符合人类对颜色的感知
- 色相(H)表示颜色的种类(红、绿、蓝等)
- 饱和度(S)表示颜色的纯度(0% 为灰色,100% 为纯色)
- 亮度(L)表示颜色的明暗(0% 为黑色,100% 为白色)
4. hslToRgb:HSL 转 RGB
功能描述:将 HSL 颜色值转换为 RGB 格式。
实现原理:
- 归一化输入:将 HSL 值转换为 0-1 范围
- 计算辅助变量:
q = L < 0.5 ? L * (1 + S) : L + S - L * Sp = 2 * L - q
- 色相转换:使用辅助函数
hue2rgb将色相转换为 RGB 分量 - 处理特殊情况:当饱和度为 0 时,RGB 三个分量都等于亮度值
代码实现:
export const hslToRgb = (h: number, s: number, l: number): RGB => {
h /= 360;
s /= 100;
l /= 100;
let r, g, b;
if (s === 0) {
r = g = b = l;
} else {
const hue2rgb = (p: number, q: number, t: number) => {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1/6) return p + (q - p) * 6 * t;
if (t < 1/2) return q;
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
return p;
};
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
const p = 2 * l - q;
r = hue2rgb(p, q, h + 1/3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1/3);
}
return {
r: Math.round(r * 255),
g: Math.round(g * 255),
b: Math.round(b * 255)
};
};
使用示例:
hslToRgb(11, 100, 60); // { r: 255, g: 87, b: 51 }
hslToRgb(0, 0, 100); // { r: 255, g: 255, b: 255 } (白色)
hslToRgb(120, 100, 50); // { r: 0, g: 255, b: 0 } (纯绿色)
算法要点:
hue2rgb函数实现了色相到 RGB 分量的非线性映射- 通过调整色相值(
h + 1/3、h、h - 1/3)来分别计算 R、G、B 分量 - 这是标准的 HSL 到 RGB 转换算法
对比色计算
5. getContrastColor:获取对比色
功能描述:根据 RGB 颜色值计算最佳对比色(黑色或白色),用于确保文本可读性。
实现原理: 使用 YIQ 颜色空间的相对亮度公式:
YIQ = (R × 299 + G × 587 + B × 114) / 1000
- 系数基于人眼对不同颜色的敏感度
- 如果 YIQ ≥ 128,返回黑色;否则返回白色
代码实现:
export const getContrastColor = (r: number, g: number, b: number): string => {
const yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;
return yiq >= 128 ? 'black' : 'white';
};
使用示例:
getContrastColor(255, 255, 255); // 'black' (白色背景用黑字)
getContrastColor(0, 0, 0); // 'white' (黑色背景用白字)
getContrastColor(255, 87, 51); // 'black' (亮色背景用黑字)
应用场景:
- 动态文本颜色选择
- 确保 UI 中的文字在任何背景色上都有良好的可读性
- 主题切换时的自动适配
替代方案:
现代浏览器支持 CSS 的 color-contrast() 函数,但在需要 JavaScript 计算的场景中,YIQ 算法仍然是一个可靠的选择。
色阶生成
6. generateShades:生成阴影色阶
功能描述:根据给定的十六进制颜色,生成5个逐渐变暗的阴影色阶。
实现原理:
- 将 HEX 转换为 RGB
- 对每个 RGB 分量按比例减少(每次减少 15%)
- 生成 5 个色阶,从浅到深
代码实现:
export const generateShades = (hex: string): string[] => {
const rgb = hexToRgb(hex);
if (!rgb) return [];
const shades = [];
for (let i = 1; i <= 5; i++) {
const factor = 1 - (i * 0.15);
shades.push(rgbToHex(
Math.round(rgb.r * factor),
Math.round(rgb.g * factor),
Math.round(rgb.b * factor)
));
}
return shades;
};
使用示例:
generateShades('#FF5733');
// [
// '#db4a2b',
// '#b73d24',
// '#93301d',
// '#6f2316',
// '#4b160f'
// ]
视觉效果:
原始色 → 阴影1 → 阴影2 → 阴影3 → 阴影4 → 阴影5
███ ███ ███ ███ ███ ███
7. generateTints:生成色调色阶
功能描述:根据给定的十六进制颜色,生成5个逐渐变亮的色调色阶。
实现原理:
- 将 HEX 转换为 RGB
- 对每个 RGB 分量向 255(白色)方向混合
- 每次混合比例增加 15%
- 生成 5 个色阶,从深到浅
代码实现:
export const generateTints = (hex: string): string[] => {
const rgb = hexToRgb(hex);
if (!rgb) return [];
const tints = [];
for (let i = 1; i <= 5; i++) {
const factor = i * 0.15;
tints.push(rgbToHex(
Math.round(rgb.r + (255 - rgb.r) * factor),
Math.round(rgb.g + (255 - rgb.g) * factor),
Math.round(rgb.b + (255 - rgb.b) * factor)
));
}
return tints;
};
使用示例:
generateTints('#FF5733');
// [
// '#ff6b4d',
// '#ff7f66',
// '#ff9380',
// '#ffa799',
// '#ffbbb3'
// ]
视觉效果:
原始色 → 色调1 → 色调2 → 色调3 → 色调4 → 色调5
███ ███ ███ ███ ███ ███
应用场景:
- 设计系统的基础色板生成
- 主题颜色的深浅变化
- UI 组件的 hover、active 状态颜色
- 数据可视化的颜色映射
完整使用示例
以下是一个综合使用示例,展示如何组合使用这些函数:
// 1. 颜色格式转换
const hex = '#FF5733';
const rgb = hexToRgb(hex); // { r: 255, g: 87, b: 51 }
const hsl = rgbToHsl(255, 87, 51); // { h: 11, s: 100, l: 60 }
const backToHex = rgbToHex(255, 87, 51); // '#ff5733'
// 2. 动态文本颜色
const backgroundColor = { r: 255, g: 87, b: 51 };
const textColor = getContrastColor(backgroundColor.r, backgroundColor.g, backgroundColor.b);
// textColor = 'black'
// 3. 生成完整色阶
const baseColor = '#FF5733';
const shades = generateShades(baseColor); // 5个阴影色
const tints = generateTints(baseColor); // 5个色调色
// 4. 构建颜色主题
const theme = {
primary: baseColor,
shades: shades,
tints: tints,
textColor: getContrastColor(...Object.values(hexToRgb(baseColor)!))
};
性能优化建议
- 缓存计算结果:对于频繁使用的颜色转换,可以考虑添加缓存机制
- 批量处理:如果需要处理大量颜色,可以考虑使用 Web Workers
- 类型检查:在生产环境中添加更严格的输入验证
总结
本文详细介绍了一套完整的颜色工具函数库,涵盖了:
✅ 格式转换:HEX ↔ RGB ↔ HSL 的完整转换链
✅ 对比度计算:基于 YIQ 算法的智能文本颜色选择
✅ 色阶生成:自动生成阴影和色调,适用于设计系统
这些函数可以广泛应用于:
- 🎨 颜色选择器组件
- 🎯 主题切换功能
- 📊 数据可视化
- 🎭 UI 组件库
- 🌈 设计工具
通过理解这些算法的实现原理,我们可以更好地在前端项目中处理颜色相关的需求,提升用户体验和开发效率。
RGB转十六进制 - 在线颜色代码转换工具 | 免费快速转换
参考资源: