怎么使用JavaScript快速实现一个颜色选择器(javascript,开发技术)

时间:2024-05-10 03:49:59 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

    在做前端界面开发的时候,遇到需要改变颜色的需求,就需要使用颜色选择器。

    针对这个问题,第一想法,自然是H5提供了input color,可以实现。但不出意外的,IE并不支持。而且,chrome的实现方式和firefox也不太一样,见下图:

    怎么使用JavaScript快速实现一个颜色选择器

    左图是chrome的,浏览器自身实现的一个颜色选择器控件;右图是firefox的,引入的是操作系统自带的颜色选择器控件。

    鉴于这些差异性,就很有必要实现一个统一的颜色选择器组件,譬如我们来实现一个类似chrome浏览器自带的这种选择器。

    要做这个组件,首先需要了解的一个知识点,就是颜色模型。

    颜色模型

    我们前端开发,最常见的颜色模型就是RGB,即红绿蓝三基色模型,而前端浏览器能支持颜色显示的颜色模型只有两种:RGB和HSL。

    其中,RGB模型是以三色的值在0-255以内的范围内,混合成一种颜色,对机器较友好,但并不太适合人直观的进行颜色选择。所以,通常的颜色选择器一般会使用另外两种更面向视觉感知的模型:HSV 和 HSL。关于颜色模型的详细知识,可见 颜色模型的基础知识。

    而chrome浏览器自带的颜色选择器,就是基于HSV的。

    HSV 与 HSL 的区别

    HSV是基于色相H(hue)、饱和度S(saturation)、明度V(Value);HSL基于色相H(hue)、饱和度S(saturation)、亮度L(lightness)。

    其中色相是一样的,本质都是一种颜色值。

    在这两个模型中,色相是以六大主色为基础,分别按60度的间隔排列在圆环上。

    这六大主色分别是:0°红、60°黄、120°绿、180°青、240°蓝、300°洋红、360°红。

    而在前端进行布局设计时,常常把圆环处理成长方形的色块,通过颜色的线性渐变方式进行分段处理,角度换算成一定的比例,如下所示:

    怎么使用JavaScript快速实现一个颜色选择器

    而饱和度和明亮度都是有区别的,为方便理解颜色选择器,本文概括简单的描述,如下:

    • HSV中的S饱和度,反映色相颜色中混入白色的值,呈现白色到色相(H)颜色的变化;

    • HSL中的S饱和度,反映色相颜色中混入灰色的值,呈现的是一种从灰色到色相(H)颜色的变化。

    • HSV中的V明度,体现的是从黑色到色相(H)颜色的过渡。

    • HSL中的L亮度,体现的是从黑色到色相(H)颜色再到白色的过渡。

    另外需要明确的是,各个部分的取值范围:Hue色相:0 - 360;饱和度和明亮度都是:0 ~ 100%。

    具体的实现上的差别,我们可以接着往下看。

    实现选择器

    色相

    色相的原理上面已经介绍了,HSV和HSL一样。落实到代码层面的话,也是很好实现的,以css和div的方式,只需要进行颜色的线性渐变即可:

    <divclass="div-bar"><!--色相柱--><divid="colorBar"class="color-bar"></div><!--滑动块--><divid="divSlider"class="div-slider"></div></div>
    .div-bar{position:relative;width:10px;height:200px;margin-left:15px;cursor:pointer;}.color-bar{background:linear-gradient(180deg,#f00,#ff017%,#0f033%,#0ff50%,#00f67%,#f0f83%,#f00);width:10px;height:200px;margin-left:20px;}.div-slider{...width:8px;height:8px;}

    这里是竖向的色相柱,宽高10 * 200,如果需要横向的改动宽高布局即可。

    计算色相柱的滑块位置

    要想移动滑块获取位置信息,首先需要监听色相柱上的鼠标事件,具体如下:

    colorBar.addEventListener('mousedown',function(e){setHueSlider(e)document.addEventListener('mousemove',setHueSlider)})document.addEventListener('mouseup',function(){document.removeEventListener('mousemove',setHueSlider)})

    在setHueSlider函数中需要处理的,就是滑块点在色相柱上的位置,然后通过计算比例得到一个hue值:

    constclientRect=colorBar.getBoundingClientRect()//获取位置信息,色柱高度-colorBarHEIGHTletyDiff=event.clientY-clientRect.topyDiff=yDiff>colorBarHEIGHT?colorBarHEIGHT:(yDiff<0?0:yDiff)//设置滑块的位置,防止滑块脱离色柱constyTop=yDiff<9?0:(yDiff-9)divSlider.style.top=yTop+'px'//色相在360度以内,计算对应的比例值,0-360color.hue=Math.round((yDiff/colorBarHEIGHT)*360*100)/100|0

    通过色相柱的滑块位置比例的计算,我们就能得到对应的色相值了。

    饱和度和明亮度

    除了色相柱以外,我们还需要设定一个基于饱和度和明亮度的颜色面板,这时候,上面对于这两块的区别介绍,就有了用武之地。

    颜色面板一般是一个长方形的区域,以HSV为例,上面提到,HSV的饱和度可以简化为白色到色相颜色的变化,如果当前的色相颜色是红色,则饱和度就是白色到红色的变化;而明亮度则体现的是黑色到红色的变化。我们在设计面板的时候,以一个长方形的面板区域:

    • 如果把面板的背景色设置为色相颜色-红色;

    • 从左到右设置饱和度,可在白色上设置从左至右的透明度变化,即最左边白色,到最右边的完全透明,线性渐变;

    • 从下到上设置明亮度,就可在最下面黑色,到最上面的完全透明,线性渐变。

    如此则可简化HSV模型里的颜色面板,在具体的实现上,可以通过下面的这个图来理解:

    怎么使用JavaScript快速实现一个颜色选择器

    当然,饱和度和明亮度在水平或者垂直方向上是可以调换的。

    要设置颜色面板,使用div+css即可,在代码实现上有多种方式,下面介绍的只使用一个div的方式,实现一个宽高300 * 200的颜色面板,(其他的方式还有使用两个div或者使用伪类等等):

    <divclass="div-panel"><!--颜色面板--><divid="colorPanel"class="color-panel"></div><!--滑块--><divid="divPicker"class="div-picker"></div></div>
    .div-panel{position:relative;width:300px;height:200px;cursor:pointer;overflow:hidden;}.color-panel{position:relative;height:200px;width:300px;background:linear-gradient(totop,#000,transparent),linear-gradient(toright,#FFF,transparent);}.div-picker{...width:12px;height:12px;}

    计算这两个值

    仍然是需要监听鼠标事件,获取鼠标位置信息,事件监听与色相的基本一样,都是监听鼠标的三个事件,这里略过。

    直接看如何计算饱和度和明亮度,根据前面的介绍与布局实现,我们定义的面板横向X轴是饱和度,面板纵向Y轴是明亮度,于是可以如下计算:

    //计算鼠标移动位置,面板宽度panelWIDTH,高度panelHEIGHTconstclientRect=colorPanel.getBoundingClientRect()letyDiff=event.clientY-clientRect.topletxDiff=event.clientX-clientRect.leftxDiff=xDiff>panelWIDTH?panelWIDTH:(xDiff<0?0:xDiff)yDiff=yDiff>panelHEIGHT?panelHEIGHT:(yDiff<0?0:yDiff)//设置滑块位置,保证滑块至少一半在面板内constyTop=yDiff-6constxLeft=xDiff-6divPicker.style.top=yTop+'px'divPicker.style.left=xLeft+'px'//饱和度和明度,这里没有取百分比的值,后续转换时需要注意color.saturation=Math.round(xDiff/panelWIDTH*100)color.value=Math.round((1-yDiff/panelHEIGHT)*100)

    hsv转rgb

    通过这样的计算,就能获取HSV对应的三个值了,后面就可以进行转换成对应RGB颜色值。

    consthsvToRgb=function(hue,saturation,value){saturation=saturation*255/100|0value=value*255/100|0if(saturation===0){return[value,value,value]}else{satVal=(255-saturation)*value/255|0ligVal=(value-satVal)*(hue%60)/60|0if(hue===360){return[value,0,0]}elseif(hue<60){return[value,satVal+ligVal,satVal]}elseif(hue<120){return[value-ligVal,value,satVal]}elseif(hue<180){return[satVal,value,satVal+ligVal]}elseif(hue<240){return[satVal,value-ligVal,value]}elseif(hue<300){return[satVal+ligVal,satVal,value]}elseif(hue<360){return[value,satVal,value-ligVal]}else{return[0,0,0]}}}

    透明度

    RGB\HSV\HSL三种颜色模型里,透明度都是独立的一个属性,不会影响到具体颜色的实现,可以单独处理这个值。
    所以,如果我们需要透明度,在布局上可以和色相柱一样,使用长条状的div,通过计算位置比例来计算当前选中的透明度值,布局如下:

    <divclass="div-alpha"><!--透明柱状--><divid="alphaBar"class="alpha-bar"></div><!--滑块--><divid="divAlphaSlider"class="div-slider"></div></div>
    .div-alpha{background-image:linear-gradient(45deg,#c5c5c525%,transparent0,transparent75%,#c5c5c50,#c5c5c5),linear-gradient(45deg,#c5c5c525%,transparent0,transparent75%,#c5c5c50,#c5c5c5);}

    在计算上,也基本和色相柱一样,只是透明度取值在0-100:

    color.alpha=Math.round(100-yDiff/alphaBarHEIGHT*100)/100

    有了透明度的值,获取颜色值时,在RGBA或这HSLA中加入透明度即可。

    基于HSL的颜色选择器

    上面讲解过HSV和HSL的区别,根据各自的特点,要实现HSL的选择器,只需要进行少许的改动。

    首先,Hue色相和透明度,两者没有区别,一模一样,不需要做任何改动。

    其次,需要改动饱和度和明亮度的颜色面板,HSL在布局时只需要改动一点,即面板的css样式:

    .color-panel{position:relative;height:200px;width:300px;/*横向X轴饱和度设置为灰的渐变,纵向Y轴设置为白到透明到黑*/background:linear-gradient(tobottom,#fff0%,transparent50%,transparent50%,#000100%),linear-gradient(toright,#8080800%,transparent100%);}

    改变颜色面板以后,获取HSL的色相、饱和度、亮度、透明度的值的方式,都与在HSV模式下一样。

    注意,这时候获取的HSLA的颜色,如果要使用到RGBA,就需要进行HSL到RGB的转换,转换函数详见 颜色模型的基础知识。

    综上,则完成了一个颜色选择器的。

    使用canvas

    除了基于div+css布局颜色选择器以外,我们还可以使用canvas来处理颜色选择器。

    在布局上,色相、面板、透明度,都使用canvas来替换,由于canvas也可以使用线性渐变,所以在设置色彩的UI布局上是没有任何问题的。

    在滑块的设计上也大致相同,只需要微小的改动,因为使用canvas以后,获取颜色的方式就不一样了。

    在canvas的色相和面板中,可以直接获取到canvas对应位置的像素点,而该像素点本身就是一个rgba的颜色值。

    所以这个带来的好处就是,我们可以省略转换过程,而直接获取到可用的颜色值。当然,不管是div还是canvas,因为布局方式和获取颜色值的方式不一样,在所能得到的颜色值的数量上会有差别,特别是canvas方式,和画布本身的像素点有关。

    但是,两种方式都可以在几百万以上的颜色值,完全满足我们的需求。

     </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
    本文:怎么使用JavaScript快速实现一个颜色选择器的详细内容,希望对您有所帮助,信息来源于网络。
    上一篇:怎么使用Pandas.concat连接DataFrame和Series下一篇:

    9 人围观 / 0 条评论 ↓快速评论↓

    (必须)

    (必须,保密)

    阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18