项目中用到了react-color-palette组件,以前对第三方组件都是不求甚解,这次想了解一下其实现细节。
简介
react-color-palette 是一个用于创建颜色调色板的 React 组件。它提供了一个简单易用的接口,让开发者可以轻松地创建和管理颜色调色板。该组件很轻量,仅依赖React、Typescript。先来看一下实例:
代码结构
项目有几个核心目录:
- components
- css
- hooks
- services
- utils
- rcp.ts
1、rcp.ts对外暴露的组件和方法,供开发者使用
2、utils提供平台无关的工具函数,比如在Vue中也可使用
3、services提供相对完整的模块工具,也具有平台无关性,以类的形式封装了Color相关的工具函数
4、hooks 提供基于React的hook工具函数,这些工具只能在React组件中使用
5、components存放各个子组件
6、css存放组件样式,这样方便将css打包成独立的文件
各司其职的组件
颜色选择器组件由多个独立组件组合而成,各个组件各司其职,相互协作,共同完成颜色选择器的功能。
- Interactive:交互组件,用于处理用户的交互操作、提供鼠标位置信息,如鼠标移动、点击等。
- Saturation:饱和度组件,基于interactive提供的鼠标位置信息计算颜色的饱和度和明度。
- Hue:色相组件,基于interactive提供的鼠标x坐标计算颜色的色相。
- Alpha:透明度组件,基于interactive提供的鼠标x坐标计算颜色的透明度。
- Fields:输入框组件,用于输入颜色的 RGB、HEX 等格式。
HSV
在具体分析各组件之前,我们先了解一下 HSV 色彩模型。
HSV是一种基于人类视觉感知的色彩模型,用于直观描述和操作颜色,它将颜色分为色相(Hue)、饱和度(Saturation)和明度(Value)三个维度。
HSV色彩模型的主要特点
- 色相(Hue):表示颜色的种类,取值范围为0到360度。色相的变化通常是从红色开始,依次经过黄色、绿色、青色、蓝色和品红色,最后回到红色。
- 饱和度(Saturation):表示颜色的纯度或浓度,取值范围为0到100%。饱和度取决于该色中含色成分和消色成分(灰色)的比例。含色成分越大,饱和度越大;消色成分越大,饱和度越小。饱和度为0时,颜色为灰度色;饱和度为100%时,颜色为纯色。
- 明度(Value):表示颜色的亮度,取值范围为0到100%。明度为0时,颜色为黑色;明度为100%时,颜色为白色。
Saturation组件
在饱和度组件中我们重点关注两个点:
- 根据鼠标位置计算颜色的饱和度和明度
- 可视化地表达颜色的饱和度和明度
1、计算饱和度和明度的代码片段
// saturation.component.tsx
const nextColor = ColorService.convert("hsv", {
...color.hsv,
s: (x / width) * 100,//饱和度计算:0%-100%之间,0%为灰色,100%为最鲜艳的颜色
v: 100 - (y / height) * 100,//明度计算:100%-0%之间,从顶部到底部
});
2、可视化地表达颜色的饱和度和明度
/* src/css/rcp.css */
.rcp-saturation {
cursor: all-scroll;
width: 100%;
position: relative;
/*
* 模拟饱和度和明度渐变效果
* 实现原理:两层线性渐变背景,一层从上到下,一层从左到右
* linear-gradient(to bottom, transparent, black):从上到下,透明到黑色,模拟出明度从高到低的变化
* linear-gradient(to right, white, transparent):从左到右,白色到透明,模拟出饱和度从左到右的变化
*/
background-image: linear-gradient(to bottom, transparent, black), linear-gradient(to right, white, transparent);
border-radius: 10px 10px 0 0;
}
// src/components/saturation/saturation.component.tsx
<div ref={saturationRef} style={{ height, backgroundColor: `hsl(${hsl})` }} className="rcp-saturation">
<div
style={{ left: position.x, top: position.y, backgroundColor: `rgb(${rgb})` }}
className="rcp-saturation-cursor"
/>
</div>
注意.rcp-saturation中的background-image和saturationRef的backgroundColor,background-image在上,backgroundColor在下,渐变过程两相叠加,展现出颜色在饱和度和明度两个纬度的渐变效果:
最终颜色 = (渐变颜色 × 渐变alpha) + (背景色 × (1 - 渐变alpha))
Hue组件
色相组件也是两点:
- 如何根据鼠标x坐标计算颜色的色相
- 可视化地表达颜色的色相
1、计算色相的代码片段
// src/components/hue/hue.component.tsx
const nextColor = ColorService.convert("hsv", {
...color.hsv,
h: (x / width) * 360,//色相计算:0-360度之间,0度为红色,360度为红色
});
2、可视化地表达颜色的色相
.rcp-hue {
cursor: ew-resize;
position: relative;
width: 100%;
height: 12px;
/*
* 借助线性渐变模拟色相渐变效果
* 实现原理:
* 一层线性渐变背景,从左到右,颜色从红色->黄色->绿色->青色->蓝色->品红->红色,
* 模拟出色相从左到右的变化
*/
background-image: linear-gradient(
to right,
rgb(255, 0, 0),/*红色,对应色相0度*/
rgb(255, 255, 0),/*黄色,对应色相60度*/
rgb(0, 255, 0),/*绿色,对应色相120度*/
rgb(0, 255, 255),/*青色,对应色相180度*/
rgb(0, 0, 255),/*蓝色,对应色相240度*/
rgb(255, 0, 255),/*品红,对应色相300度*/
rgb(255, 0, 0)/*回到红色,对应色相360度*/
);
border-radius: 10px;
}
Alpha组件
同样两点:
1、计算透明度
2、显示透明度效果
重要的工具
src/services/color/color.service.ts提供了颜色转换的重要方法,使得可以在HSV、RGB、HEX等数据形式间相互转换。在任何其他项目中都可以使用其中的方法。
思考
代码不是一串生硬的字符,它需要带有现实的意义,它要能更好的去帮人们解决现实的问题