零依赖、链式调用、可变对象:重新设计 JavaScript 颜色处理体验

2 阅读2分钟

做前端这么多年,每次处理颜色都有种说不出的别扭。现有方案要么太重、要么 API 设计反直觉,有的追求不可变性导致代码繁琐,有的插件丰富但体积臃肿。

于是就有了 @xpyjs/color


痛点

  • chroma.js 太大,压缩后 30KB+
  • colord 走不可变路线,每次操作返回新对象,调试麻烦
  • tinycolor2 TS 支持弱
  • 没有一家把「可变对象 + 完整色彩空间 + 轻量」三者同时做到

核心理念

@xpyjs/color 的设计哲学只有三个词:可变、完整、轻量

可变对象

直接修改原对象,不需要频繁创建新实例:

const color = new Color('#ff6b6b')
color.lighten(0.1)
color.saturate(0.2)
console.log(color.hex()) // 输出调整后的颜色

当然,如果你想保留原对象的色值,还可以使用 .clone() 来复制一个新对象:

const color1 = new Color('#ff6b6b')
const color2 = color1.clone().lighten(0.1).saturate(0.2) // color1 对象被保留,并且生成一个新值赋给 color2

完整色彩空间

支持 8 种色彩空间,覆盖日常和专业场景:

  • HEX / RGB / HSL / HSV
  • XYZ / LAB / LCH / OKLAB
const color = new Color('#ff6b6b')

color.hex()   // '#ff6b6b'
color.rgb()   // { r: 255, g: 107, b: 107 }
color.hsl()   // { h: 0, s: 100, l: 71 }
color.lab()   // { l: 64.7, a: 59.4, b: 51.2 }

零依赖 + 轻量

  • 纯原生 JS,无任何外部依赖
  • 压缩后约 4KB(gzipped)
  • TypeScript-first,完整类型提示,开箱即用

链式调用

所有操作都支持链式,代码流畅可读:

import { Color } from '@xpyjs/color'

const result = new Color('#ff6b6b')
  .lighten(0.15)
  .saturate(0.3)
  .alpha(0.85)
  .hex() // '#ff9b9b'

插件系统

内置方法相当丰富,并且还内置 20+ 插件,按需扩展使用:

类别插件
色彩空间cmyk, lab, hwb, oklab, a98Rgb, displayP3, proPhotoRgb, rec2020, xyz, name
调整harmony, scale
运算blend, gradient, palette, temperature
转换percentageRgb, simulate
辅助a11y, theme
  • 全部都有完整的类型提示
  • 针对更现代的内容进行适配
  • 更丰富的插件配置

对比 colord

colord 是个好库,但它的不可变设计在高频调整场景下会很痛苦:

// colord(不可变)
const c = new Colord('#ff6b6b')
const adjusted = c.lighten(0.1).saturate(0.2) // 返回新对象,原对象不变

// @xpyjs/color(可变)
const c = new Color('#ff6b6b')
c.lighten(0.1).saturate(0.2) // 直接修改原对象

如果你的颜色频繁修改,或者你喜欢「所见即所得」的调试体验,也许可变方案更适合你。


安装

npm install @xpyjs/color

开源

项目地址:github.com/xpyjs/color

欢迎 star、issues 和 PR,一起让颜色处理变得更好用 🦋