@skyroc/color
专业级色彩工具包,提供三种调色板生成算法(Ant Design、推荐算法、OKLCH)、颜色格式转换、WCAG 无障碍对比度检测与暗色模式支持
概述
@skyroc/color 是一个专业级颜色工具包,面向设计系统和主题引擎场景,提供:
- 三种调色板生成算法:Ant Design HSV 算法、基于 Tailwind 色板的推荐算法、OKLCH 感知均匀算法
- 基础颜色操作:格式转换(hex/rgb/hsl/hsv)、混合、透明度、明暗调节
- 1500+ 色名匹配:输入任意颜色,返回最近的自然语言色名
- WCAG 无障碍:对比度计算、AA/AAA 等级判断、自动推荐文字色
- 暗色模式:反转明度曲线生成暗色主题色板
- 内置 Tailwind 色板数据:22 个色族、每族 11 档(50–950)
底层依赖 colord(基础颜色解析与转换)和 culori(OKLCH 色彩空间与 WCAG 对比度)。
API
调色板生成 — 统一入口
getColorPalette
根据输入颜色生成 11 档色板,通过 algorithm 参数选择三种算法之一:
function getColorPalette(
color: AnyColor,
algorithm?: PaletteAlgorithm // default: 'antd'
): Map<ColorPaletteNumber, string>| 参数 | 说明 |
|---|---|
color | 任意合法颜色值(hex、rgb、hsl、css 色名等) |
algorithm | 'antd'(默认)Ant Design HSV 算法;'recommended' 推荐算法;'oklch' OKLCH 感知均匀算法 |
import { getColorPalette } from '@skyroc/color';
// Ant Design 算法(默认)
const antdMap = getColorPalette('#1677ff');
console.log(antdMap.get(500)); // 主色
// 推荐算法
const recommendMap = getColorPalette('#1677ff', 'recommended');
console.log(recommendMap.get(300)); // 300 档色值
// OKLCH 算法
const oklchMap = getColorPalette('#1677ff', 'oklch');
console.log(oklchMap.get(500)); // 感知均匀的主色getPaletteColorByNumber
快捷取指定色阶的 hex 值:
function getPaletteColorByNumber(
color: AnyColor,
number: ColorPaletteNumber,
algorithm?: PaletteAlgorithm // default: 'antd'
): stringimport { getPaletteColorByNumber } from '@skyroc/color';
const hex = getPaletteColorByNumber('#1677ff', 200);
const oklchHex = getPaletteColorByNumber('#1677ff', 200, 'oklch');调色板生成 — Ant Design 算法
基于 Ant Design 的 HSV 色彩空间算法。以输入色为第 6 档(主色),向浅色方向(1-5 档)递增亮度、递减饱和度,向深色方向(7-11 档)递减亮度、递增饱和度,同时对色相做小幅偏移。
getAntDPaletteColorByIndex
按 ColorIndex(1-11)取单个色阶:
function getAntDPaletteColorByIndex(
color: AnyColor,
index: ColorIndex // 1-11,6 为主色
): stringimport { getAntDPaletteColorByIndex } from '@skyroc/color';
const main = getAntDPaletteColorByIndex('#1677ff', 6); // 主色,原色返回
const light = getAntDPaletteColorByIndex('#1677ff', 1); // 最浅
const dark = getAntDPaletteColorByIndex('#1677ff', 11); // 最深getAntDColorPalette
生成完整 11 档色板,支持暗色主题变体:
function getAntDColorPalette(
color: AnyColor,
darkTheme?: boolean, // default: false
darkThemeMixColor?: string // default: '#141414'
): string[]暗色模式通过将各档与 darkThemeMixColor 按预设透明度混合生成,适合深色背景场景。
import { getAntDColorPalette } from '@skyroc/color';
// 亮色主题
const lightPalette = getAntDColorPalette('#1677ff');
// => ['#e6f4ff', '#bae0ff', ..., '#001d66', '#00114d']
// 暗色主题
const darkPalette = getAntDColorPalette('#1677ff', true);
// 自定义暗色混合底色
const customDark = getAntDColorPalette('#1677ff', true, '#1a1a2e');调色板生成 — 推荐算法
通过 CIE76 色差(deltaE)在内置 Tailwind 色板中找到最近色族,然后以输入色与匹配色阶的 HSL 色相差和饱和度比率为基准,对该色族的每一档做色相偏移与饱和度缩放,生成风格一致的 11 档色板。
getRecommendedColorPalette
返回完整的 ColorPaletteMatch,包含色族名、所有色阶、主色(500 档)和匹配色:
function getRecommendedColorPalette(color: string): ColorPaletteMatchimport { getRecommendedColorPalette } from '@skyroc/color';
const result = getRecommendedColorPalette('#6366f1');
console.log(result.name); // 色族名
console.log(result.main.hex); // 500 档 hex
console.log(result.match.number); // 输入色最接近的色阶编号
console.log(result.colorMap.get(200)); // 取 200 档getRecommendedPaletteColorByNumber
快捷取推荐色板中指定色阶:
function getRecommendedPaletteColorByNumber(
color: string,
number: ColorPaletteNumber
): string调色板生成 — OKLCH 算法
基于 OKLCH 感知均匀色彩空间的专业调色板生成器,灵感来自 Apple Human Interface Guidelines。相比 HSV/HSL,OKLCH 能保证不同色相在同一明度下的视觉亮度一致。
核心特性:
- 数据驱动明度曲线:基于 Tailwind 官方色板的 OKLCH 分析数据
- 色相感知色度补偿:不同色相有不同的最佳色度-明度曲线(黄色在高亮度峰值,蓝色在低亮度峰值)
- Apple 风格色相旋转:暖色越亮越偏黄、越暗越偏红;冷色反之
- 二分法 sRGB 色域映射:在保留最大色彩饱满度的前提下确保 sRGB 可显示
generateOklchPalette
基础 OKLCH 色板生成:
function generateOklchPalette(color: string): ColorPaletteFamilyimport { generateOklchPalette } from '@skyroc/color';
const family = generateOklchPalette('#6366f1');
console.log(family.name); // 自动命名
console.log(family.palettes); // 11 档 { hex, number }[]getOklchColorPalette
返回 ColorPaletteMatch,自动找到与输入色最接近的色阶:
function getOklchColorPalette(color: string): ColorPaletteMatchimport { getOklchColorPalette } from '@skyroc/color';
const result = getOklchColorPalette('#6366f1');
console.log(result.match.number); // 输入色匹配到的色阶
console.log(result.main.hex); // 500 档getOklchPaletteColorByNumber
快捷取指定色阶的 hex:
function getOklchPaletteColorByNumber(
color: string,
number: ColorPaletteNumber
): stringgenerateOklchPaletteAdvanced
支持自定义配置的高级生成:
function generateOklchPaletteAdvanced(
color: string,
options?: OklchPaletteOptions
): ColorPaletteFamilyimport { generateOklchPaletteAdvanced } from '@skyroc/color';
// 关闭色相旋转,使用自定义明度曲线
const palette = generateOklchPaletteAdvanced('#6366f1', {
appleHueShift: false,
lightnessCurve: [0.97, 0.94, 0.89, 0.82, 0.74, 0.66, 0.58, 0.50, 0.43, 0.38, 0.26],
});
// 强制输入色为 600 档
const palette600 = generateOklchPaletteAdvanced('#6366f1', {
forceStep: 600,
});generateOklchPaletteEx
精确保留输入色的增强版本。在匹配档位上使用原始输入色(不做任何近似),并附带每档的 OKLCH 数值与 CSS 字符串:
function generateOklchPaletteEx(
color: string,
forceStep?: ColorPaletteNumber
): ColorPaletteFamilyWithOklchimport { generateOklchPaletteEx } from '@skyroc/color';
const result = generateOklchPaletteEx('#6366f1');
console.log(result.matchedStep); // 500
console.log(result.palettes[5].hex); // '#6366f1'(精确保留)
console.log(result.palettes[5].oklchCss); // 'oklch(55.69% 0.215 277.01)'
console.log(result.inputOklchCss); // 输入色的 OKLCH CSS
// 强制放在 600 档
const result600 = generateOklchPaletteEx('#6366f1', 600);
console.log(result600.palettes[6].hex); // '#6366f1'WCAG 无障碍
getContrastRatio
计算两个颜色之间的 WCAG 对比度(范围 1-21):
function getContrastRatio(color1: string, color2: string): numberimport { getContrastRatio } from '@skyroc/color';
const ratio = getContrastRatio('#1677ff', '#ffffff');
console.log(ratio); // e.g. 3.98meetsWcagContrast
判断对比度是否满足 WCAG 要求:
function meetsWcagContrast(
ratio: number,
level?: WcagLevel, // default: 'AA'
textSize?: TextSize // default: 'normal'
): boolean| 等级 | 正常文字 | 大号文字 |
|---|---|---|
| AA | >= 4.5 | >= 3.0 |
| AAA | >= 7.0 | >= 4.5 |
import { getContrastRatio, meetsWcagContrast } from '@skyroc/color';
const ratio = getContrastRatio('#1677ff', '#ffffff');
meetsWcagContrast(ratio, 'AA', 'normal'); // false(4.5 要求)
meetsWcagContrast(ratio, 'AA', 'large'); // true(3.0 要求)generateOklchPaletteWithContrast
生成色板并附带完整的 WCAG 对比度分析:
function generateOklchPaletteWithContrast(color: string): PaletteContrastInfoimport { generateOklchPaletteWithContrast } from '@skyroc/color';
const info = generateOklchPaletteWithContrast('#1677ff');
// 查看各档与白色的对比度
info.contrastVsWhite.forEach((ratio, number) => {
console.log(`${number}: ${ratio.toFixed(2)}`);
});
// 白底上满足 AA 的色阶
console.log(info.passAAonWhite); // e.g. [600, 700, 800, 900, 950]
// 每档推荐的文字颜色(黑或白)
console.log(info.recommendedTextColor.get(500)); // '#ffffff' 或 '#000000'findAccessibleTextColor
在色板中找到满足 WCAG AA 标准的最佳文字色阶:
function findAccessibleTextColor(
paletteColor: string,
backgroundColor: string,
preferDark?: boolean // default: true
): ColorPaletteNumber | nullimport { findAccessibleTextColor } from '@skyroc/color';
// 在白色背景上,用 #1677ff 色板中找深色文字
const step = findAccessibleTextColor('#1677ff', '#ffffff', true);
console.log(step); // e.g. 700
// 在深色背景上找浅色文字
const lightStep = findAccessibleTextColor('#1677ff', '#1a1a2e', false);暗色模式
generateDarkModePalette
使用反转的明度曲线生成暗色主题色板。50 档最暗(L=0.18),950 档最亮(L=0.96):
function generateDarkModePalette(color: string): ColorPaletteFamilyimport { generateDarkModePalette } from '@skyroc/color';
const darkPalette = generateDarkModePalette('#1677ff');
// darkPalette.palettes[0].hex → 50 档(最暗)
// darkPalette.palettes[10].hex → 950 档(最亮)基础颜色工具
格式转换
import {
isValidColor,
getHex,
getRgb,
getHsl,
getHsv,
transformHslToHex,
} from '@skyroc/color';
isValidColor('#1677ff'); // true
isValidColor('not-a-color'); // false
getHex('rgb(22, 119, 255)'); // '#1677ff'
getRgb('#1677ff'); // { r: 22, g: 119, b: 255, a: 1 }
getHsl('#1677ff'); // { h: 215, s: 100, l: 54, a: 1 }
getHsv('#1677ff'); // { h: 215, s: 91, v: 100, a: 1 }
transformHslToHex({ h: 215, s: 100, l: 54 }); // '#1677ff'色差计算
import { getDeltaE } from '@skyroc/color';
// CIE76 色差(0 = 完全相同,1 = 最大差异)
const delta = getDeltaE('#1677ff', '#1890ff');
console.log(delta); // e.g. 0.035透明度与混合
import { addColorAlpha, mixColor, transformColorWithOpacity } from '@skyroc/color';
// 添加透明度
addColorAlpha('#1677ff', 0.5); // '#1677ff80'
// 混合两种颜色
mixColor('#1677ff', '#ff4d4f', 0.5); // 50% 混合
// 将半透明色转为在指定背景上的不透明近似色
// 适合不支持透明度的场景(如某些 PDF 渲染器)
transformColorWithOpacity('#1677ff', 0.3); // 白底近似
transformColorWithOpacity('#1677ff', 0.3, '#000000'); // 黑底近似明暗调节
import { adjustLightness, lightenColor, darkenColor, isWhiteColor } from '@skyroc/color';
// adjustLightness:正数变亮,负数变暗(范围 -100 到 100)
adjustLightness('#1677ff', 20); // 变亮
adjustLightness('#1677ff', -20); // 变暗
// lightenColor / darkenColor(范围 0-100)
lightenColor('#1677ff', 20);
darkenColor('#1677ff', 20);
// 判断是否为白色
isWhiteColor('#ffffff'); // true
isWhiteColor('#fafafa'); // false色名匹配
import { getColorName } from '@skyroc/color';
// 在 1500+ 色名表中查找最近匹配
getColorName('#1677ff'); // e.g. 'Dodger Blue'
getColorName('#ff0000'); // 'Red'
getColorName('#2ecc71'); // e.g. 'Shamrock'匹配算法综合 RGB 欧氏距离和 HSL 距离(HSL 权重为 2 倍),先做精确匹配,未命中时取加权距离最小的色名。
内置数据
colorPalettes
Tailwind 风格的预设色板数据,包含 22 个色族:
import { colorPalettes } from '@skyroc/color';
// 色族列表
const names = colorPalettes.map(f => f.name);
// ['Slate', 'Gray', 'Zinc', 'Neutral', 'Stone',
// 'Red', 'Orange', 'Amber', 'Yellow', 'Lime',
// 'Green', 'Emerald', 'Teal', 'Cyan', 'Sky',
// 'Blue', 'Indigo', 'Violet', 'Purple', 'Fuchsia',
// 'Pink', 'Rose']
// 每族 11 档 (50, 100, 200, ..., 950)
const bluePalette = colorPalettes.find(f => f.name === 'Blue');
console.log(bluePalette?.palettes);
// [{ hex: '#eff6ff', number: 50 }, ..., { hex: '#172554', number: 950 }]这些预设数据被推荐算法用作 deltaE 匹配的参照基准。
三种算法对比
| Ant Design | 推荐算法 | OKLCH | |
|---|---|---|---|
| 色彩空间 | HSV | HSL + deltaE | OKLCH(感知均匀) |
| 色阶数量 | 11 档(索引 1-11) | 11 档(50-950) | 11 档(50-950) |
| 主色位置 | 第 6 档 | 500 档 | 500 档(可自定义) |
| 感知均匀性 | 一般 | 依赖预设数据 | 优秀 |
| 色度补偿 | 无 | 无 | 有(按色相族自适应) |
| 色相旋转 | 线性偏移 | 等比映射 | Apple 风格自然旋转 |
| 暗色模式 | 混色法 | 不支持 | 反转明度曲线 |
| WCAG | 不支持 | 不支持 | 完整支持 |
| sRGB 色域映射 | 无 | 无 | 二分法精确映射 |
| OKLCH 值输出 | 不支持 | 不支持 | 支持(generateOklchPaletteEx) |
| 适用场景 | 兼容 Ant Design 生态 | 需要 Tailwind 风格一致性 | 设计系统、无障碍要求高的场景 |
选择建议:
- 需要与 Ant Design 组件库保持一致 → Ant Design 算法
- 希望生成的色板风格接近 Tailwind 预设 → 推荐算法
- 追求感知均匀、需要 WCAG 合规、或构建独立设计系统 → OKLCH 算法
使用场景
主题色生成
从品牌色一键生成完整色板,用于 CSS 变量或设计 Token:
import { generateOklchPaletteEx } from '@skyroc/color';
const brand = generateOklchPaletteEx('#6366f1');
// 输出为 CSS 变量
brand.palettes.forEach(({ hex, number, oklchCss }) => {
console.log(`--color-primary-${number}: ${hex};`);
console.log(`--color-primary-${number}-oklch: ${oklchCss};`);
});无障碍合规检测
确保界面文字在各色阶背景上可读:
import { generateOklchPaletteWithContrast } from '@skyroc/color';
const info = generateOklchPaletteWithContrast('#1677ff');
// 找出适合做白底文字的色阶
console.log('白底 AA 合规色阶:', info.passAAonWhite);
// 为每档自动选择黑/白文字
info.recommendedTextColor.forEach((textColor, step) => {
console.log(`${step} 档背景 → 文字用 ${textColor}`);
});暗色/亮色主题切换
同一品牌色生成亮色和暗色两套色板:
import { generateOklchPalette, generateDarkModePalette } from '@skyroc/color';
const brandColor = '#1677ff';
const lightPalette = generateOklchPalette(brandColor);
const darkPalette = generateDarkModePalette(brandColor);
// 亮色主题:50 最浅 → 950 最深
// 暗色主题:50 最暗 → 950 最亮(明度反转)透明色转不透明
在不支持透明度的渲染环境中(如某些邮件客户端、PDF),将半透明色转为视觉等效的不透明色:
import { transformColorWithOpacity } from '@skyroc/color';
// 在白色背景上,30% 透明度的蓝色等效于什么不透明色?
const opaqueOnWhite = transformColorWithOpacity('#1677ff', 0.3);
// 在深色背景上
const opaqueOnDark = transformColorWithOpacity('#1677ff', 0.3, '#1a1a2e');核心类型
ColorPaletteNumber
色板色阶编号,主色为 500:
type ColorPaletteNumber = 50 | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 | 950;ColorPalette
单个色阶:
type ColorPalette = {
hex: string;
number: ColorPaletteNumber;
};ColorPaletteFamily
一组色阶组成的色族:
type ColorPaletteFamily = {
name: string;
palettes: ColorPalette[];
};ColorPaletteMatch
调色板匹配结果,包含完整色族、色阶映射、主色和匹配色:
type ColorPaletteMatch = ColorPaletteFamily & {
colorMap: Map<ColorPaletteNumber, ColorPalette>;
main: ColorPalette; // 500 档
match: ColorPalette; // 与输入色最接近的档
};ColorIndex
Ant Design 算法使用的 1-11 索引,第 6 档为主色:
type ColorIndex = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11;PaletteAlgorithm
调色板生成算法选择:
type PaletteAlgorithm = 'antd' | 'oklch' | 'recommended';| 值 | 算法 | 说明 |
|---|---|---|
'antd' | Ant Design HSV | 经典 HSV 色彩空间算法,兼容 Ant Design 生态 |
'recommended' | 推荐算法 | 基于内置 Tailwind 色板进行 deltaE 匹配 + HSL 比例调整 |
'oklch' | OKLCH 感知均匀 | 基于 OKLCH 色彩空间,支持色度补偿、色相旋转、sRGB 色域映射 |
OklchPaletteOptions
OKLCH 高级生成选项:
interface OklchPaletteOptions {
/** 是否启用 Apple 风格色相旋转 @default true */
appleHueShift?: boolean;
/** 是否启用色度补偿 @default true */
chromaCompensation?: boolean;
/** 自定义明度曲线(11 个值,从亮到暗) */
lightnessCurve?: number[];
/** 强制将输入色放在指定色阶 */
forceStep?: ColorPaletteNumber;
/** 是否在输出中包含 OKLCH 值 @default false */
includeOklch?: boolean;
}ColorPaletteWithOklch / ColorPaletteFamilyWithOklch
带 OKLCH 数值与 CSS 字符串的扩展类型:
interface ColorPaletteWithOklch extends ColorPalette {
oklch: { l: number; c: number; h: number };
oklchCss: string; // e.g. "oklch(58.5% 0.204 277.1)"
}
interface ColorPaletteFamilyWithOklch {
name: string;
palettes: ColorPaletteWithOklch[];
matchedStep: ColorPaletteNumber;
inputOklch: { l: number; c: number; h: number };
inputOklchCss: string;
}WCAG 相关类型
type WcagLevel = 'AA' | 'AAA';
type TextSize = 'normal' | 'large';
interface PaletteContrastInfo {
palette: ColorPaletteFamily;
contrastVsWhite: Map<ColorPaletteNumber, number>;
contrastVsBlack: Map<ColorPaletteNumber, number>;
passAAonWhite: ColorPaletteNumber[];
passAAonBlack: ColorPaletteNumber[];
recommendedTextColor: Map<ColorPaletteNumber, '#ffffff' | '#000000'>;
}架构
src/
├── types/ 类型定义(ColorPalette、ColorPaletteNumber 等)
├── shared/ 基础工具
│ ├── colord.ts colord 封装(格式转换、混合、明暗调节等)
│ └── name.ts 色名匹配(1500+ 色名表最近距离查找)
├── constant/ 内置数据
│ ├── name.ts 色名表 [hex, name][] + hex → name 映射
│ └── palette.ts Tailwind 风格预设色板(22 个色族 × 11 档)
└── palette/ 三种调色板生成算法
├── index.ts 统一入口(getColorPalette / getPaletteColorByNumber)
├── antd.ts Ant Design HSV 算法(11 档,主色在第 6 档)
├── recommend.ts 推荐算法(deltaE 最近色族 + HSL 比例调整)
└── oklch.ts OKLCH 感知均匀算法(含 WCAG、暗色模式)三种算法的数据流向:
输入颜色 (any CSS color)
│
├──► Ant Design 算法
│ HSV 空间 → 色相偏移 + 饱和度/亮度步进 → 11 档色板
│
├──► 推荐算法
│ deltaE 匹配内置色族 → HSL 色相/饱和度比例映射 → 11 档色板
│
└──► OKLCH 算法
OKLCH 空间 → 色度补偿 + 色相旋转 + sRGB 色域映射 → 11 档色板
+ WCAG 对比度分析
+ 暗色模式变体