
现代JavaScript颜色处理库 高效精准轻量级
@texel/color是一个现代JavaScript颜色处理库,为实时应用、生成艺术和网页图形提供高效解决方案。该库支持快速颜色转换、色差计算、色域映射和序列化,在速度和精确度方面表现出色。支持OKLCH、DisplayP3等现代颜色空间,并可通过tree-shaking优化包体积。相比其他类似库,性能提升5-125倍,内存占用更低。

这是一个简洁现代的JavaScript颜色库。特别适用于实时应用、生成艺术和网页图形。
使用npm安装并导入模块。
npm install @texel/color --save
将OKLCH(OKLab的圆柱形式)转换为sRGB:
import { convert, OKLCH, sRGB } from "@texel/color"; // L = 0 .. 1 // C = 0 .. 0.4 // H = 0 .. 360(度) const rgb = convert([0.5, 0.15, 30], OKLCH, sRGB); // 注意sRGB输出范围为0 .. 1 // -> [ 0.658, 0.217, 0.165 ]
你也可以使用通配符导入:
import * as colors from "@texel/color"; const rgb = colors.convert([0.5, 0.15, 30], colors.OKLCH, colors.sRGB);
:bulb: 现代打包工具(esbuild、vite)会应用树摇,移除未使用的功能,如代码中未引用的色彩空间和色域映射函数。上述脚本使用esbuild打包后约3.5kb。
另一个使用色域映射和序列化的宽色域Canvas2D示例:
import { gamutMapOKLCH, DisplayP3Gamut, sRGBGamut, serialize } from "@texel/color"; // 可能在或不在sRGB色域内的值 const oklch = [ 0.15, 0.425, 30 ]; // 决定要映射到哪个色域 const isDisplayP3Supported = /* 检查环境 */; const gamut = isDisplayP3Supported ? DisplayP3Gamut : sRGBGamut; // 将输入的OKLCH映射到R,G,B空间(sRGB或DisplayP3) const rgb = gamutMapOKLCH(oklch, gamut); // 获取输出空间的CSS颜色字符串 const color = serialize(rgb, gamut.space); // 在Canvas2D上下 文中绘制颜色 const canvas = document.createElement('canvas'); const context = canvas.getContext('2d', { colorSpace: gamut.id }); context.fillStyle = color; context.fillRect(0,0, canvas.width, canvas.height);
output = convert(coords, fromSpace, toSpace, output = [0, 0, 0])将coords(通常为[r,g,b]或[l,c,h]等)从fromSpace转换到指定的toSpace。from和to空间是spaces接口之一。
你可以传入output,一个三维向量,结果将存储在其中。这可用于避免在热代码路径中分配新内存。
返回值是目标空间的新坐标;如sRGB空间的目标为[r,g,b]。注意,大多数空间使用归一化且无界的坐标;所以RGB空间的范围是0..1,可能会超出范围(即超出色域)。你可能需要结合gamutMapOKLCH使用,见下文。
output = gamutMapOKLCH(oklch, gamut = sRGBGamut, targetSpace = gamut.space, out = [0, 0, 0], mapping = MapToCuspL, [cusp])执行Björn Ottoson描述的(2021)快速OKLCH色域映射。接受OKLCH空间的输入[l,c,h]坐标,确保最终结果在指定的颜色gamut内(默认sRGBGamut)。你可以进一步指定不同的目标空间(默认为色域的空间),例如获取线性光sRGB并避免传递函数,或保持结果在OKLCH中:
import { gamutMapOKLCH, sRGBGamut, sRGBLinear, OKLCH } from "@texel/color"; // 映射到sRGB但返回线性sRGB const lrgb = gamutMapOKLCH(oklch, sRGBGamut, sRGBLinear); // 或映射到sRGB但返回OKLCH(不执行RGB裁剪) const lch = gamutMapOKLCH(oklch, sRGBGamut, OKLCH);
你可以指定out数组以避免分配,结果将存储在该数组中。你还可以指定mapping函数,决定色域映射时使用的策略,可以是以下之一:
import { // 可能的映射 MapToL, MapToGray, MapToCuspL, MapToAdaptiveGray, MapToAdaptiveCuspL, } from "@texel/color"; // 执行sRGB色域映射时保持亮度 const rgb = [0, 0, 0]; gamutMapOKLCH(oklch, sRGBGamut, sRGB, rgb, MapToL);
cusp也可作为最后一个参数传入,允许对已知色相进行更快的评估。见下文计算cusp。
注意: 如果映射到基于OKLab的目标(OKLCH、OKHSL等),将跳过最后的RGB裁剪步骤。这会产生更可预测的OKLab和OKLCH结果,但在转换为可显示颜色时,你可能需要执行最后的clampedRGB()步骤。
LC = findCuspOKLCH(a, b, gamut, out = [0, 0])找到给定OKLab色相平面(用OKLab空间中的归一化a和b值表示)的'cusp',返回[L, C](亮度和色度)。当你在已知色相上工作时,这对预计算色域映射的某些方面很有用:
import { sRGBGamut, findCuspOKLCH, gamutMapOKLCH, degToRad, MapToCuspL, } from "@texel/color"; const gamut = sRGBGamut; // 为这个色相计算一次cusp const H = 30; // 例如30º色相 const hueAngle = degToRad(H); const a = Math.cos(hueAngle); const b = Math.sin(hueAngle); const cuspLC = findCuspOKLCH(a, b, gamut); // ... 在程序的其他地方 ... // 传入'cusp'参数以 加快评估 // 假设你的OKLCH坐标与cusp有相同的色相(H) gamutMapOKLCH(oklch, gamut, gamut.space, out, MapToCuspL, cuspLC);
a和b也可以来自OKLab坐标,但必须归一化使a^2 + b^2 == 1。
str = serialize(coords, inputSpace, outputSpace = inputSpace)将指定的coords(假定在inputSpace中)转换为字符串,如果需要,先转换到指定的outputSpace。如果空间是sRGB,为了浏览器兼容性和性能,将使用普通的rgb(r,g,b)字符串(字节形式),否则将返回CSS颜色字符串。注意,并非所有空间(如某些线性空间)目前都受CSS支持。你可以选择在coords数组中传入第四个元素作为alpha分量(0..1范围)。
import { serialize, sRGB, DisplayP3, OKLCH } from "@texel/color"; serialize([0, 0.5, 1], sRGB); // "rgb(0, 128, 255)" serialize([0, 0.5, 1, 0.5], sRGB); // "rgba(0, 128, 255, 0.5)" serialize([0, 0.5, 1], DisplayP3); // "color(display-p3 0 0.5 1)" serialize([0, 0.5, 1, 0.35], DisplayP3); // "color(display-p3 0 0.5 1 / 0.35)" serialize([1, 0, 0], OKLCH, sRGB); // "rgb(255, 255, 255)" serialize([1, 0, 0], OKLCH); // "oklch(1 0 0)"
info = deserialize(colorString)这是serialize的反向操作,它会接收一个字符串,确定它引用的色彩空间id,以及3个或4个(含透明度)coords。这个功能有意地限制了范围,只支持十六进制RGB、rgb()和rgba()字节值,以及oklch()、oklab()和不带修饰符的普通color()函数。
import { deserialize } from "@texel/color"; const { coords, id } = deserialize("color(display-p3 0 0.5 1 / 0.35)"); console.log(id); // "display-p3" console.log(coords); // [ 0, 0.5, 1, 0.35 ]
注意: 解析仍然是API设计中正在进行的工作,复杂的CSS颜色字符串处理不在本库的范围内。
delta = deltaEOK(oklabA, oklabB)在OKLab空间中计算两个坐标之间的颜色差异。由于这是一个感知均匀的色彩空间,改进了CIELAB及其缺陷,因此在许多情况下它应该可以适当地替代CIEDE2000颜色差异方程。
[utils]该模块还导出了许多其他实用工具。
该模块导出了一组色彩空间:
import { XYZ, // 使用D65白点 XYZD50, // 使用D50白点 sRGB, sRGBLinear, DisplayP3, DisplayP3Linear, Rec2020, Rec2020Linear, A98RGB, // Adobe® 1998 RGB A98RGBLinear, ProPhotoRGB, ProPhotoRGBLinear, OKLab, OKLCH, OKHSL, // 在sRGB色域内 OKHSV, // 在sRGB色域内 // 列出所有空间的函数 listColorSpaces, } from "@texel/color"; console.log(listColorSpaces()); // [XYZ, sRGB, sRGBLinear, ...] console.log(sRGBLinear.id); // "srgb-linear" console.log(sRGB.base); // -> sRGBLinear console.log(sRGB.fromBase(someLinearRGB)); // -> [gamma编码的sRGB...] console.log(sRGB.toBase(someGammaRGB)); // -> [线性sRGB...]
注意,并非所有空间都有base字段;如果未指定,则假定色彩空间可以通过OKLab或XYZ作为根进行传递。
该模块导出了一组"色域",这些色域是由OKLab空间中的近似值定义的边界,允许快速进行色域映射。这些接口主要由gamutMapOKLCH函数使用。
import { sRGBGamut, DisplayP3Gamut, Rec2020Gamut, A98RGBGamut, // 列出所有色域的函数 listColorGamuts, } from "@texel/color"; console.log(listColorGamuts()); // [sRGBGamut, ...] console.log(sRGBGamut.space); // sRGB空间 console.log(sRGBGamut.space.id); // 'srgb'
注意:目前尚不支持ProPhoto色域,我欢迎通过Python脚本修复它的PR。
除了核心API外,该模块还导出了许多实用工具:
b = floatToByte(f)将0..1范围内的浮点数转换为0..255范围内的字节,进行四舍五入并限制在范围内。
out = XYZ_to_xyY(xyz, out=[0,0,0])将XYZ坐标转换为xyY形式,如果指定了out,则将结果存储在其中后返回。
out = xyY_to_XYZ(xyY, out=[0,0,0])将xyY坐标转换为XYZ形式,如果指定了out,则将结果存储在其中后返回。
v = lerp(min, max, t)使用因子t在min和max之间执行线性插值。
v = lerpAngle(min, max, t)使用因子t在min和max之间执行圆形线性插值,其中min和max被视为角度(以度为单位),允许值在0到360之间环绕,插值以创建最短的弧。
c = clamp(value, min, max)将value限制在min和max之间,并返回结果。
out = clampedRGB(inRGB, out=[0,0,0])将RGB限制( 即裁剪)在0..1范围内,如果指定了out,则将结果存储在其中后返回。
inside = isRGBInGamut(rgb, epsilon = 0.000075)如果给定的rgb在其0..1色域边界内,则返回true,阈值为epsilon。
rgb = hexToRGB(hex, out=[0,0,0])将指定的十六进制字符串(带或不带前导#)转换为0..1范围内的浮点RGB三元组,如果指定了out,则将结果存储在其中后返回。
hex = RGBToHex(rgb)将指定的RGB三元组(0..1范围内的浮点数)转换为带前导#的6字符十六进制颜色字符串。
angle = constrainAngle(angle)将angle(以度为单位)限制在0..360范围内,必要时进行环绕。
degAngle = radToDeg(radAngle)将角度(以弧度为单位)转换为度。
radAngle = degToRad(degAngle)将角度(以度为单位)转换为弧度。
您还可以导入更低级别的函数和矩阵;这可能对细粒度转换有用,或者例如将缓冲区上传到WebGPU以进行计算着色器。
import { OKLab_to, OKLab_from, transform, XYZ_to_linear_sRGB_M, LMS_to_XYZ_M, XYZ_to_LMS_M, sRGB, OKHSLToOKLab, DisplayP3Gamut, } from "@texel/color"; console.log(XYZ_to_linear_sRGB_M); // [ [a,b,c], ... ] OKLab_to(oklab, LMS_to_XYZ_M); // OKLab -> XYZ D65 OKLab_from(xyzD65, XYZ_to_LMS_M); // XYZ D65 -> OKLab transform(xyzD65, XYZ_to_linear_sRGB_M); // XYZ D65 -> sRGBLinear sRGB.fromBase(in_linear_sRGB, out_sRGB); // 线性到gamma传递函数 sRGB.toBase(in_sRGB, out_linear_sRGB); // gamma到线性传递函数 // 非sRGB色域中的OKHSL // 另见OKHSVToOKLab及其反函数 OKHSLToOKLab([h, s, l], DisplayP3Gamut, optionalOutVec);
该库目前只公开了{ lerp, lerpAngle }函数。要插值颜色,您需要构建一些额外的逻辑,例如,请参见example-interpolation.js脚本,该脚本在Canvas2D中创建颜色渐变。
您可以构建自定义色彩空间对象来扩展这个库,例如添加对CIELab和HSL的支持。有关示例,请参见test/spaces/lab.js和test/spaces/hsl.js。其中一些空间可能在以后添加到库中,尽管当前重点是"现代"空间(如OKLab,它在很大程度上使CIELab和HSL过时)。自定义色彩空间的文档正在编写中。
Colorjs非常出色,可能是JavaScript中当前领先的标准,但它对于创意编码和实时Web应用程序来说并不是很实用,在这些应用程序中,要求通常是(1)更精简的代码库,(2)高度优化,以及(3)最小化GC抖动。
Colorjs,以及类似的Culori,专注于匹配CSS规范,这意味着它很可能会随着时间的推移继续增加复杂性,性能通常会受到影响(例如,@texel/color的尖点交叉色域映射比Colorjs快约125倍,比culori快约60倍)。
还有许多其他选项,如 color-space 或 color-convert,但这些不支持现代色彩空间,如 OKLab 和 OKHSL,和/或具有可疑的准确度(例如,许多库不区分 XYZ 中的 D50 和 D65 白点)。
本库并不旨在涵盖所有色彩空间;它只专注于有限的"现代"集合,即 OKLab、OKHSL 和 DeltaEOK 在许多实际用途中已经取代了 CIELab、HSL 和 CIEDE2000,使得本库更简单、更精简。请注意,其他空间如 CIELab 和 HSL 可通过"自定义色彩空间"得到支持。
该模块使用了以下一些做法,以显著优化性能并减小打包体积:
所有转换都经过测试,与 Colorjs 转换近似相等,误差在 2<sup>-33</sup>(10 位小数)以内,在某些情况下甚至更准确。
本库使用 coloraide 及其 Python 工具计算转换矩阵和 OKLab 色域近似值。一些矩阵已硬编码到脚本中,并尽可能使用有理数(如 CSS 颜色模块工作草案规范 中 建议 的那样)。
如果您认为矩阵或准确度可以改进,请提交 PR。
test 目录中有几个基准测试:
npm run bench 与 colorjs 进行比较npm run bench:node 获取 node 性能分析npm run bench:size 使用 esbuild 获取小型打包大小以下结果基于 MacBook Air M2。请注意,Colorjs 的性能取决于您使用的 API(默认的基于类的 API 比过程式 API 慢得多)。
<details> <summary>与 Colorjs.io 的基准对比</summary>转换(Colorjs.io 过程式 API)--
Colorjs.io:2955.88 毫秒
我们的:457.86 毫秒
加速:快 6.5 倍
转换(Colorjs.io 主要 API)--
Colorjs.io:10034.38 毫秒
我们的:452.11 毫秒
加速:快 22.2 倍
OKLCH - sRGB 色域映射(Colorjs.io 过程式 API)--
Colorjs.io:5602.46 毫秒
我们的:49.10 毫秒
加速:快 114.1 倍
OKLCH - sRGB 色域映射(Colorjs.io 主要 API)--
Colorjs.io:5913.80 毫秒
我们的:44.91 毫秒
加速:快 131.7 倍
所有空间到 P3 的色域映射(Colorjs.io 过程式 API)--
Colorjs.io:4693.43 毫秒
我们的:150.16 毫秒
加速:快 31.3 倍
所有空间到 P3 的色域映射(Colorjs.io 主要 API)--
Colorjs.io:5478.16 毫秒
我们的:145.88 毫秒
加速:快 37.6 倍
</details>
<details>
<summary>与 Culori 的基准对比</summary>
使用输入类型:OKLab L 平面的随机采样进行测试
OKLCH 到 P3 的转换 --
Culori:43.30 毫秒
我们的:12.83 毫秒
加速:快 3.4 倍
OKLCH 到 P3 色域的色域映射 --
Culori:1588.62 毫秒
我们的:23.05 毫秒
加速:快 68.9 倍
</details>
克隆,npm install,然后运行 npm run 列出可用的脚本,或运行 npm t 执行测试。
这个库的实现得益于许多开发者和工程师的出色前期工作:
MIT 许可,详见 LICENSE.md。


免费创建高清无水印Sora视频
Vora是一个免费创建高清无水印Sora视频的AI工具


最适合小白的AI自动化工作流平台
无需编码,轻松生成可复用、可变现的AI自动化工作流

大模型驱动的Excel数据处理工具
基于大模型交互的表格处理系统,允许用户通过对话方式完成数据整理和可视化分析。系统采用机器学习算法解析用户指令,自动执行排序、公式计算和数据透视等操作,支持多种文件格式导入导出。数据处理响应速度保持在0.8秒以内,支持超过100万行数据的即时分析。


AI辅助编程,代码自动修复
Trae是一种自适应的集成开发环境(IDE),通过自动化和多元协作改变开发流程。利用Trae,团队能够更快速、精确地编写和部署代码,从而提高编程效率和项目交付速度。Trae具备上下文感知和代码自动完成功能,是提升开发效率的理想工具。


AI论文写作指导平台
AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。


AI一键生成PPT,就用博思AIPPT!
博思AIPPT,新一代的AI生成PPT平台,支持智能生成PPT、AI美化PPT、文本&链接生成PPT、导入Word/PDF/Markdown文档生成PPT等,内置海量精美PPT模板,涵盖商务、教育、科技等不同风格,同时针对每个页面提供多种版式,一键自适应切换,完美适配各种办公场景。


AI赋能电商视觉革命,一站式智能商拍平台
潮际好麦深耕服装行业,是国内AI试衣效果最好的软件。使用先进AIGC能力为电商卖家批量提供优质的、低成本的商拍图。合作品牌有Shein、Lazada、安踏、百丽等65个国内外头部品牌,以及国内10万+淘宝、天猫、京东等主流平台的品牌商家,为卖家节省将近85%的出图成本,提升约3倍出图效率,让品牌能够快速上架。


企业专属的AI法律顾问
iTerms是法大大集团旗下法律子品牌,基于最先进的大语言模型(LLM)、专业的法律知识库和强大的智能体架构,帮助企业扫清合规障碍,筑牢风控防线,成为您企业专属的AI法律顾问。


稳定高效的流量提升解决方案,助力品牌曝光
稳定高效的流量提升解决方案,助力品牌曝光


最新版Sora2模型免费使用,一键生成无水印视频
最新版Sora2模型免费使用,一键生成无水印视频
最新AI工具、AI资讯
独家AI资源、AI项目落地

微信扫一扫关注公众号