最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 你知道 react-color 的实现原理吗

    正文概述 掘金(Jacob是我了)   2021-01-10   501

    一、前言


    ReactColor 是一个优秀的 React 颜色选择器组件,官方给了多种布局供开发者选择。

    你知道 react-color 的实现原理吗

    笔者常用的主题为 Sketch,这种主题涵盖了颜色面板推荐色块RGB颜色输入等功能,比较完善。但是最近在写一个富文本编辑器,编写过程中遇到了一些问题,比如用户在点击推荐色块时,编辑器会失去焦点,无法对字体颜色进行更改。如果是编辑器自有的组件,可以使用以下代码

    event.preventDefault();
    

    该代码可以禁止浏览器默认行为,比如点击推荐色块之后只将色值向上传递,而不改变浏览器当前 focus 状态。但是 ReactColor 并没有暴露该事件,故 clone 了源码,在编辑器内集成了该组件,实现功能的同时也能够减少打包体积。

    二、实现原理


    本章节主要介绍 ReactColor 的实现原理,以比较有代表性的 Sketch 主题为例。

    你知道 react-color 的实现原理吗

    由上图可以看到,整个颜色选择器面板由这六个部分组成,分别是亮度与饱和度调节面板色相 Hue 调节面板透明度调节面板当前颜色的 RGBA 与 Hex 值推荐色块以及颜色实时预览。下面的部分就来介绍其原理实现。

    2.1 HSV 色彩模型


    与颜色相关的几个属性分别为亮度、饱和度、色相与透明度,与我们平时用到的 RGB 色彩模型不同,ReactColor 中用的是 HSV 色彩模型,其具体含义如下:

    你知道 react-color 的实现原理吗

    下面是维基百科对 HSV 色彩模型的介绍:


    至于为什么选用 HSV 色彩模型而不是直接使用 RGB,大家在使用 ReactColor 的过程中应该会发现,只要在下方的 色相 Hue 调节面板上选中了颜色,亮度与饱和度调节面板就会呈现什么颜色。举个例子:你选择了黄色,那么最上方调节面板呈现的就是黄色,差别也只是饱和度与明度不同而已。这就是使用 HSV 色彩模型的优势,让用户选择的颜色变成可预知并且方便调节的。

    RGB 颜色空间利用三个颜色分量的线性组合来表示颜色,任何颜色都与这三个分量有关,而且这三个分量是高度相关的,所以连续变换颜色时并不直观,想对图像的颜色进行调整需要更改这三个分量才行。自然环境下获取的图像容易受自然光照、遮挡和阴影等情况的影响,即对亮度比较敏感。而 RGB 颜色空间的三个分量都与亮度密切相关,即只要亮度改变,三个分量都会随之相应地改变,而没有一种更直观的方式来表达,而这就是 HSV 色彩模型的优势所在。

    2.2 HSV 转 RGB


    上面提到,在日常的前端开发过程中还是普遍使用 RGB 色彩模型进行颜色表示,在用户设置好 HSV 值后我们需要将其转为 RGB 值,公式如下(该公式来自维基百科)

    hi=h/60h_i = \lfloor h/60 \rfloorhi​=⌊h/60⌋

    f=h/60hif = h/60 - h_if=h/60−hi​

    p=v(1s)p = v * (1-s)p=v∗(1−s)

    q=v(1fs)q = v*(1-f*s)q=v∗(1−f∗s)

    t=v(1(1f)s)t = v * (1 - (1-f)*s)t=v∗(1−(1−f)∗s)

    你知道 react-color 的实现原理吗


    这样在用户选择完成后就可以对色彩空间实时转换,通过 onChange 回调返回给用户。

    2.3 HSV 色彩模型在 ReactColor 中的实现


    既然使用了 HSV 色彩模型就要考虑一下如何表示这三个变量,下面我们分两部分来讲。

    2.3.1 Hue 色相

    颜色名称红绿蓝含量角度代表物体
    红色R255,G0,B0血液、草莓橙色R255,G128,B030°火、橙子黄色R255,G255,B060°香蕉、杧果黄绿R128,G255,B090°柠檬绿色R0,G255,B0120°草、树叶青绿R0,G255,B128150°军装青色R0,G255,B255180°水面、天空靛蓝R0,G128,B255210°水面、天空蓝色R0,G0,B255240°海、墨水紫色R128,G0,B255270°葡萄、茄子品红R255,G0,B255300°火、桃子紫红R255,G0,B128330°墨水


    如何横向表示色相呢,只需要一行 CSS 代码:

    background: linear-gradient(to right, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%);
    

    这样即可大致表达出 0-360 度的色相值,效果如下:
    你知道 react-color 的实现原理吗
    根据鼠标拖动的位置距离左边界的距离就可以计算出色相值。

    /**
     * 在颜色值发生变化时实时计算相应的色相值
     * @param event
     */
    const handleChange = (event: any) => {
      if (!ref.current) {
        return;
      }
      const clientRect = ref.current.getBoundingClientRect();
      const { width: containerWidth } = clientRect;
      const x: number = typeof event.pageX === 'number' ? event.pageX : event.touches[0].pageX;
      const left = x - (clientRect.left + window.pageXOffset);
    
      let innerHue;
      // 处理边界值
      if (left < 0) {
        innerHue = 0;
      } else if (left > containerWidth) {
        innerHue = 359;
      } else {
        const percent = (left * 100) / containerWidth;
        innerHue = (360 * percent) / 100;
      }
      setHue(innerHue);
      props.onChange({ h: innerHue });
    };
    

    2.3.2 Saturation 饱和度与 Value 明度

    饱和度(S) 是指色彩的纯度,越高色彩越纯,低则逐渐变灰,取0-100%的数值。明度(V) 指颜色的亮度,不同的颜色具有不同的明度。

    在 ReactColor 中按照如下方式来表示饱和度与明度。
    你知道 react-color 的实现原理吗
    其实用 CSS 表示也比较简单,使用渐变色来表示就可以实现该效果。

    background: linear-gradient(to right, #fff, rgba(255, 255, 255, 0));
    background: linear-gradient(to top, #000, rgba(0, 0, 0, 0));
    

    与色相的计算方式一样,也是根据鼠标拖动的位置距离左边界和下边界的距离来计算,计算方法可以参考色相的思路。

    三、总结


    大家看完这篇文章应该发现代码部分其实我介绍的不多,更多还是介绍 HSV 色彩模型,以及作者为什么没有使用 RGB 表示。

    如果大家去看 react-color 源码就会发现代码其实不难理解,难点还是在 HSV 的应用方法上面,大家如果有需要自己在项目里面定制化颜色选择器的话也可以根据这个思路来,一天之内就可以写出来。

    四、参考资料

    • HSL和HSV色彩空间
    • 色相
    • 明度
    • 饱和度

    起源地下载网 » 你知道 react-color 的实现原理吗

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元