理解了 HSL 颜色表示法,就能实现 ColorPicker 组件

选择颜色是常见需求,想必大家都用过 ColorPicker 组件。

比如 Chrome DevTools 的这个:

antd 也有 ColorPicker 组件:

其实浏览器原生也支持 color 类型的 input:

功能更强大,还支持网页颜色吸取。

兼容性也很不错:

那为什么 antd 还在 5.5 版本实现一个 ColorPicker 呢?

应该主要是为了统一 UI 吧,浏览器原生组件各个浏览器都不一样。

比如 safari 的 <input type="color"/> 是这样的:

safari 的这个做的还挺复杂的,还有一个原生的窗口来做选择,支持的功能挺多:

但这样会导致产品在各个浏览器的体验是不一致的。

出于这个原因,我们会用 antd 的 ColorPicker 组件,而不是原生的 color 类型的 input。

那这个颜色选择组件是怎么实现的呢?

这就要学习一些颜色的知识了。

颜色有很多种表示法,RGB 是最常用的,分别是 red、green、blue,还可以用十六进制标识法 #FFFFFF

R、G、B 的取值范围是 0 到 255。

颜色用空格或者逗号分隔都行,最后的 / 后面是透明度,可以用百分比或者小数:

此外,HSL 标识法也很常用,分别是色相、饱和度、亮度,/ 后面是透明度。

色相的取值范围是 0 到 360

饱和度和亮度都是 0% 到 100%

那为什么还会有 0.3turn、150deg 这种单位呢?

因为色相是色相环上的颜色:

美术生应该很熟悉这种色相环,什么相差 60 度是邻近色、相差 180 度是互补色等等。

所以取值范围是 0 到 360 也就是共 360 度。

0.3 turn 就是一圈的 0.3 的地方的颜色,而 150 deg 就是 150 度的地方的颜色。

有 RGB 不就好了么?为啥还要搞个 HSL?

红绿蓝是计算机存储颜色的方式,它喜欢这种表示法,可以直接用来显示颜色。

但是对人来说,是不是还是明暗关系、色彩饱和度更容易理解一点?

所以选色的时候都是基于色相、饱和度、亮度这些东西,但存储的时候使用 RGB,最后屏幕显示颜色也是基于 RGB的。

此外,还有 HSV/HSB,这俩用明度而不是亮度,都是差不多的东西:

所以说,HSL 对人很友好,调解下明暗度、色彩饱和度等很直观。在网页里支持 RGB 和 HSL 这俩表示法。

颜色选择器一般都是基于 HSL 来做的:

你拖动下面的色彩条的时候,调节的就是色相环的位置,色相环为 0 的时候是红色、色相环 360 的时候也是红色,正好转一圈。

你拖动上面的滑块的时候,调节的就是饱和度和亮度。

图中可以看到色相没变,往下滑亮度减少、往左滑饱和度减少。

是不是很直观?调节颜色的体验很好?

那如果用 RBG 来做这种颜色调节呢?

safari 的颜色选择器里就有这个,是这样的:

是不是用起来一脸懵逼?

怎么就变成粉色了,怎么又变紫色了?

不止你懵逼,设计师用起来也懵逼。

所以颜色选择器一般都是 HSL 的,调节色相、饱和度、亮度这三者,而不是直接调节 RGB。

最后显示的时候才转成 RGB。

rgb 和 hsl 的互转算法都是固定的,可以安装用 @swiftcarrot/color-fns 这个包来做:

然后我们具体来看下 ColorPicker 的每一部分怎么实现:

下面这个透明度滑块很容易理解,拖动改变的是透明度,从 0% 到 100%,

滑块设置一个渐变背景就行。

上面色相的滑块也差不多,取值范围是 0 到 360

但它的渐变设置比较麻烦,不是两个颜色的渐变。不然从红色渐变到红色么?

而是根据取色相环不同角度的颜色来设置渐变:

比如取 0、60、120、180、240、360 这些角度共 7 个颜色来渐变:

取出的值是 0 到 360 的色相值。

最后,上面的调整饱和度亮度的部分又是怎么实现的呢?

其实也很简单,也是加了渐变,把渐变去掉就是纯色了。

一共两个渐变:

从下到上是黑色到透明的渐变。

我一般都是写 linear-gradient(to top, xxx,xxx),用 0deg 也可以。看 devtools 标出的小圆圈也很直观。

然后从左到右是从拜到透明的渐变。

这样,就可以根据 left、top 的值,计算出饱和度和亮度的值,从上到下饱和度从 100% 到 0%,从由向左饱和度从 100% 到 0%。

这样通过 3 个滑块,就实现了任意透明度、任意色相、亮度、饱和度的颜色的选取。

之后再转成计算机喜欢的 RGB 就好了。

这就是 ColorPicker 的实现原理。

有同学可能会问,那这个吸色器呢?

这个东西可不是网页里实现的,这个是原生组件,可以很方便的拿到网页渲染的结果,然后取色。

不过浏览器现在也有这个 api 了,叫做 EyeDropper

用起来很简单:

效果也很好:

但是你看看这个惨不忍睹的兼容性:

如果你要吸取颜色,还是用原生组件 <input type="color"/>好了。

总结

选择颜色是常见需求,可以用浏览器的 <input type="color"/> 的原生标签,也可以用 antd 的 ColorPicker 组件。

原生标签虽然支持的功能多,但是各个浏览器实现不一致。

实现这样的颜色选择组件,需要了解颜色表示法:

网页支持的颜色表示法有 RGB、HSL 两种:

RGB 是计算机喜欢的颜色表示法,可以直接用红绿蓝来显示颜色。

HSL 是人更喜欢的颜色表示法,用色相、饱和度、亮度来表示颜色,最后转成 RGB。

(HSV/HSB 和 HSL 是一样的东西,只不过叫明度而不是亮度)

ColorPicker 一般都是用 HSL 来实现的,通过滑块调节色相、饱和度、亮度,显示的时候加上几个渐变,就能实现这种组件:

理解了 HSL 颜色表示法,就能实现 ColorPicker 组件。

相关推荐
崔庆才丨静觅1 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60612 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了2 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅2 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅2 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅3 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment3 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅3 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊3 小时前
jwt介绍
前端
爱敲代码的小鱼3 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax