Core Docs

@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'
): string
import { 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 为主色
): string
import { 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): ColorPaletteMatch
import { 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): ColorPaletteFamily
import { 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): ColorPaletteMatch
import { 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
): string

generateOklchPaletteAdvanced

支持自定义配置的高级生成:

function generateOklchPaletteAdvanced(
  color: string,
  options?: OklchPaletteOptions
): ColorPaletteFamily
import { 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
): ColorPaletteFamilyWithOklch
import { 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): number
import { getContrastRatio } from '@skyroc/color';

const ratio = getContrastRatio('#1677ff', '#ffffff');
console.log(ratio); // e.g. 3.98

meetsWcagContrast

判断对比度是否满足 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): PaletteContrastInfo
import { 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 | null
import { 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): ColorPaletteFamily
import { 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
色彩空间HSVHSL + deltaEOKLCH(感知均匀)
色阶数量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 对比度分析
                                                            + 暗色模式变体

On this page