当前位置: 首页 > Web前端 > vue.js

如何封装一个颜色选择ColorPicker组件?

时间:2023-03-31 20:58:14 vue.js

本文主要分为两部分进行讲解。首先带大家进一步了解颜色模型相关的概念,然后在此基础上封装一个ColorPicker组件。同时文末还会分享一个前端小技巧,不要错过哦!颜色模型在我们日常开发中,我们经常使用的颜色模型主要是十六进制和RGB。浏览器支持的颜色模型还包括颜色标识符和HSL。作为前端开发者,基本上只需要照搬设计稿中给定的颜色值即可,但是如果要封装一个选色组件,就得了解这些颜色模型的原理。RGB和十六进制中最直观的颜色模型应该是RGB,比较简单。它主要将颜色分为红、绿、蓝三个通道,分别对应R、G、B。然后将每个通道分成256(0~255)个等级来表示颜色的强度。根据屏幕的三基色原理,可以合成出我们需要的各种颜色。它能表示的颜色有256**3=16777216种,远远超出了人眼所能识别的颜色范围。十六进制也属于RGB颜色模型,只是显示形式不同。它将RGB表示的十进制值转换为十六进制,每个颜色通道(0~255)的十六进制为(00~FF),同样以#开头。例如:当所有颜色通道为0时,显示的颜色为全黑,RGB表示rgb(0,0,0),十六进制表示#000000或#000;当所有颜色通道为255时,显示颜色为Allwhite,RGB表示rgb(255,255,255),十六进制表示#ffffff或#fff;同理,蓝色、绿色、红色表示每个通道的值设置最大,其他通道的值设置最小。虽然RGB三通道模型非常直观,可以表示如此多的颜色,但很明显,人们很难调出自己想要的颜色。因为当我们需要一种颜色时,很难人为地控制哪个通道需要更多的颜色,哪个颜色通道需要设置得更小。专业人士凭经验大概能叫出来,但对于我们用户小白来说,基本无计可施。HSL和HSV(很关键)针对以上问题,我们不得不了解另外两种颜色模型:HSL和HSV。这两种颜色模型非常相似,所以把它们放在一起,了解这两种颜色显示的原理,就能玩出很多花样。HSL主要将颜色分为色相(H:hue)、饱和度(S:saturation)和亮度(L:lightness)三个通道,其中最重要的是色相(H)。色调H以红、绿、蓝三原色为基础,用360°的圆圈表示。红色为0°,绿色为120°,蓝色为240°。并在红色和绿色之间添加60°的黄色,在绿色和蓝色之间添加180°的青色,在蓝色和红色之间添加300°的品红色。然后通过这6种颜色的过渡,得到一个360°的色相环。饱和度S是指颜色的强度或纯度,用0~100%的百分比表示。值越高,颜色越鲜艳,值越低,颜色越暗。呈现的是从灰色到色调的过渡。亮度L是颜色的明暗程度,也用0~100%的百分比表示。主要反应是色彩中的黑白两色。小于50%时混入的黑色越多,大于50%时混入的白色越多。当值为0时,显示颜色为纯黑色,当值为100%时,显示颜色为纯白色,与其他两个通道的值无关。HSV模型和HSL模型一样,H也是色调的意思,区别是S和V(值)。饱和度S虽然也指颜色的纯度,但它反映的是白色混入的高低,数值越大,白色混入越少,颜色越纯,数值越小,白色混入越多。值为0,显示为纯白色。明度V它所表达的明暗程度是指与黑色混合的程度。数值越小,黑色混入越多,数值越大,黑色混入越少。当数值为0时,表现为纯黑色。组件UI的实现了解了这些颜色模型的原理,那么我们现在就可以开始编码了。细心的同学应该发现了,为什么要引入HSV模型呢?浏览器实际上并不支持这种颜色模型。其实这主要是为了封装组件的需要。市面上的选色组件基本都是按照HSV颜色模型实现的。至于为什么,一是为了统一,一些共识标准不应该改变;二来也应该方便UI的实现,需要将这些三维的颜色模型展开成二维的,HSV更符合人的直觉视觉。如何展开?一般将色相H展开为一维线性形状(用0°~360°的圆或线段表示);将饱和度S和明度V展开成一个二维矩形,x轴表示饱和度S,y轴表示明度V;如果需要透明度A,再添加一个一维线段。上面不重点讲透明度,因为这些颜色模型的透明度都是一样的,可以看成是一般的颜色通道。再看UI的实现(注:组件基于uniapp+vue3,只展示部分代码):hue的实现.hue{/*色调:从左到右分别是红、黄、绿、青、蓝、品红,等渐变*/背景:线性渐变(向右,#f000%,#ff017%,#0f033%,#0ff50%,#00f67%,#f0f83%,#f00100%);}饱和度和亮度矩形的实现其中hColor表示色相圈中选择的颜色。.s-mask{/*饱和度x轴实现:从左到右,纯白色>>>透明渐变*/背景:linear-gradient(toright,#fff,rgba(255,255,255,0));}.v-mask{高度:150px;/*亮度y轴的实现:从下往上,纯黑>>>透明渐变*/background:linear-gradient(totop,#000,rgba(0,0,0,0));}放一个最终效果图:如果想看具体效果,可以到我的微信小程序体验,搜索【绘画】找到。组件逻辑实现中用到的第三方库:color-convert主要是针对不同颜色模型之间的数值转换。如果有时间,也可以了解一下它们之间的转换算法,自己实现。定义组件的props:constprops=defineProps({value:{type:String,default:'#000',},});为了兼容所有颜色模型,在获取到props参数后,需要将其转化为我们组件内部实现的HSV模型。constsetDefaultValue=(color:string)=>{让defaultHSV:HSV=[0,0,0];如果(/^#/.test(color)){defaultHSV=hex.hsv(color);}elseif(/^rgb/.test(color)){defaultHSV=rgb.hsv(color.match(/\d+/g)asunknownasRGB);}elseif(/^hsl/.test(color)){defaultHSV=hsl.hsv(color.match(/\d+/g)asunknownasHSL);}elseif(/^hsv/.test(color)){defaultHSV=color.match(/\d+/g)与HSL一样未知;}console.log(color,'===>hsv',defaultHSV);}得到HSV的值后,我们就可以初始化我们的组件了。由于代码量大,就不贴代码了。大概是初始化拖动控件的偏移量。同时,在组件内部修改颜色后,还需要通过事件传递。不要忘记将HSV模型转换为浏览器可以识别的模型。constemit=defineEmits<{(event:'change',value:string):void;}>();触发时机可以是实时的touchmove,也可以是touchend,也可以在组件内部添加一个确认按钮来触发。根据个人需求和表现,我在touchend上触发了change事件。颜色选择组件ColorPicker的封装就在这里。最后分享一个干货的小福利。颜色转换技巧如何快速将其他颜色模型转换为RGB?直接看代码:const$div=document.createElement('div');$div.style.color='red';document.body.appendChild($div);constcolorRGB=window.getComputedStyle($div).color;console.log(colorRGB);//rgb(255,0,0)document.body.removeChild($div);将上面的代码直接复制到你的浏览器控制台试试看,主要是通过浏览器原生APIgetComputedStyle,它可以自动将浏览器支持的任何颜色转换成RGB/RGBA返回。最后感谢大家的阅读,觉得不错记得点赞分享哦!文中各组件的实现效果,可以参考我的小程序【画画】体验,也可以关注我的公众号【末日码农】获取更多技术知识~