跟随网上教程学习前端知识迄今为止3个月,这个色彩选择器是根据网上教程的任务所做的,在此之前,我完全不知道也没想过JavaScript居然还能做这样一个东西,所以刚开始看到这个任务的时候是一头雾水。以下是我做这个色彩选择器的过程。

  • .我学过用HTML和CSS做一个静态的网页,但是我是不了解HTML5的,我大概浏览了一下别人所写的代码,看到了<canvas>这个元素标签,查找之后,知道它是一个画布,那么如何产生色彩选择器的颜色就确定了。
    我在刚开始学的时候有上网了解过,他人的建议大概是:要自己多思考怎么写,不是拿别人的代码。而我碰到不会的任务时,我的做法是,比如这次的画布,我先看了别人的代码,然后我会记录下来别人代码里出现的我所没见过的元素标签、JS对象的属性和方法,但不是直接采用别人的想法(实际上我不太看的懂别人的代码,有些也没有注释,有时候自己有头绪写速度反而比看别人的更快),然后去查找,这会让我有一个头绪,接下来自己慢慢写,我不知道这样一个方法是不是比较好的学习方法,希望有好方法的人看到这段文字并且恰巧又有时间的话,可以帮忙提供给我,先说声谢谢!);
  • 做颜色选择器得了解颜色的知识,在那个任务下有学员提供了一份笔记,我自己理解了后,如下(我写的时候是用chorm看效果的):
    色彩选择器demo
    R——红色,G——绿色,B——blue,也就是三原色; H——色相,S——饱和度,L——明度;以及将RGB或者HSL转为十六进制来代表颜色。PS上的色彩选择器有一个色相条,它是将12色相环(所以H的取值就是0°~360°)头尾拆开变成条形,在色相环的画布上利用渐变来”上色“;

      //颜色棒的渐变 var context2=bar.getContext("2d"); var  grd2 = context2.createLinearGradient(0,0,0,600); grd2.addColorStop(0,"rgb(255,0,0)"); grd2.addColorStop(1/6,"rgb(255,255,0)"); grd2.addColorStop(1/3,"rgb(0,255,0)"); grd2.addColorStop(1/2,"rgb(0,255,255)"); grd2.addColorStop(2/3,"rgb(0,0,255)"); grd2.addColorStop(5/6,"rgb(255,0,255)"); grd2.addColorStop(1,"rgb(255,0,0)"); context2.fillStyle=grd2; context2.fillRect(0,0,10,600) 

    而左边大画布上的颜色变化是随着色相的变化而变化的,也就是H值0°~360°。在色相条上滑动圆形选择器时,利用getImageData()的方法来获取发生变化时相应的颜色值,但是不是利用putImageData()将颜色填充到画布上,因为画布上的颜色还有一个饱和度和明度的变化,所以画布上的颜色应该是从左至右有一个饱和度的变化,即从白色渐变到色相条上被选择的颜色,这个颜色是变化的,所以可以在其变化时将其作为一个函数的参数传递到函数,执行函数,然后进行渐变;同时画布上明度的变化,也可以被包括在该函数中,下面是从色相条上获取颜色的方法,有一点值得注意的是,色相条上的颜色变化来自色相条上颜色的变化,而右下角方框的颜色变化来自画布上圆形选择器的颜色变化,所以色相条上的颜色变化导致的一系列变化有:色相条上圆形选择器的背景色变化和画布上颜色的变化 → 画布上颜色发生变化,那么位于画布上圆形选择器选中颜色的变化 → RGB和HSL值的变化,展示方框颜色的变化

move.οnmοusedοwn=function(event){flag=true;
//这里的全局变量是让鼠标移动的时候可以取点击时的值          moveTop=move.offsetTop;nowY=event.clientY;} document.addEventListener("mousemove",function(event){var  moveY=event.clientY;dis=moveY-nowY;finalTop=moveTop+dis; if(flag){if(bar.offsetTop+bar.offsetHeight-(move.offsetHeight/2)-1>=finalTop && finalTop>=bar.offsetTop-   (move.offsetHeight/2)){
//if里面的条件是色相条上的圆形选择器从圆中心开始计算选色的位置,所以要减去它高度的一般,另外,前面的再减去1,是因为getImageData()不能从色相的最底部取一像素的值,这样取来的是浏览器的背景色,所以应该让圆心的位置上移一个像素,即减1。move.style.top=finalTop+"px";colorH=finalTop+move.offsetHeight/2-barTop; var  imgData=context2.getImageData(0,colorH,1,1);//将rgb转为16进制var strHex="#";for(var i=0 ; i〈3; i++){ var hex = Number(imgData.data[i]).toString(16);if(hex.length===1){//基于rgb转16进制的原理,如果长度为1,那么在前面加0hex="0"+hex; }strHex  +=  hex;}bgcolor=strHex;render(bgcolor); //渲染主色板move.style.backgroundColor=bgcolor;//颜色棒上的圆形选择器移动时,以下函数改变RGB和HslpickRenderShow();}}})

render()的函数如下:

function  render(color){//水平渐变var context1=myCanvas.getContext("2d");var  grd1 = context1.createLinearGradient(0,0,600,0);grd1.addColorStop(0,'rgba(255,255,255,1)');grd1.addColorStop(1,color);context1.fillStyle=grd1;context1.fillRect(0,0,600,600);//垂直渐变var  grd3 = context1.createLinearGradient(0,0,0,600);grd3.addColorStop(0,'rgba(0, 0, 0, 0)');grd3.addColorStop(1,'rgba(0, 0, 0, 1)');context1.fillStyle=grd3;context1.fillRect(0,0,600,600);}

另外关于颜色之间转换的公式,我是抄的别人的代码,即javascript HEX十六进制与RGB, HSL颜色的相互转换
求出RGB值和HSL值的函数pickRenderShow()如下:

//通过渲染板上圆形选择器移动而产生的拾色,右下角展示板渲染,各个值的显示变化function  pickRenderShow(){//渲染板上的圆形择色器circleCenterY=circleSelect.offsetTop-myCanvas.offsetTop+circleSelect.offsetWidth/2; circleCenterX=circleSelect.offsetLeft-myCanvas.offsetLeft+circleSelect.offsetWidth/2; //用来到达渲染板上圆形选择器中心点位置,然后取宽高各为一像素的像素点var imageData=context1.getImageData(circleCenterX,circleCenterY,1,1);showBGcolorR=imageData.data[0];showBGcolorG=imageData.data[1];showBGcolorB=imageData.data[2];colorR.value=showBGcolorR;colorG.value=showBGcolorG;colorB.value=showBGcolorB;//根据渲染板上圆形择色器的rgb,转为16进制,将值填入右边一栏var str="#";for(var i=0; i〈3; i++){ var hex = Number(imageData.data[i]).toString(16);if(hex.length===1){hex="0"+hex;  //基于rgb转16进制的原理,如果长度为1,那么在前面加0}str  +=  hex;}//将rgb转换为HslshowBGcolorR /= 255, showBGcolorG /= 255, showBGcolorB /= 255;var max=Math.max(showBGcolorR,showBGcolorG,showBGcolorB);var min=Math.min(showBGcolorR,showBGcolorG,showBGcolorB);L=(max+min)/2;if(max==min){H=0;S=0;}else{var  d=max-min;S=L>0.5 ? d/(2-max-min):d/(max+min);switch(max){case showBGcolorR: H=60*((showBGcolorG - showBGcolorB)/d+(showBGcolorG 〈showBGcolorB ? 6 : 0)); break;case showBGcolorG: H=60*( (showBGcolorB - showBGcolorR) / d + 2); break;case showBGcolorB: H=60*((showBGcolorR - showBGcolorG) / d + 4); break;}} colorh.value=Math.round(H);colorS.value=Number(S.toFixed(2)); //将小数点转换为2位,再将字符串转换为数字colorL.value=Number(L.toFixed(2)); //使右边颜色展示板能够随左边圆形择色器的改变而改变var context3=show.getContext("2d");context3.fillStyle=str;context3.fillRect(0,0,100,100);colorHex.value=str; }

3.如果移动画布上圆形选择器,那么RGB和HSL,颜色展示框都会随之变化,这和上面的pickRenderShow()一样,就是多加了一个,不能让圆形选择器移出画布之外:

//渲染板上圆形选择器的移动 circleSelect.addEventListener("mousedown",function(event){ selectflag=true; downX=event.clientX; downY=event.clientY; circleTop=circleSelect.offsetTop; circleLeft=circleSelect.offsetLeft; }) document.addEventListener("mousemove",function(event){ var  moveX=event.clientX; var  moveY=event.clientY; var  circleNowL=(moveX-downX)+circleLeft; var  circleNowT=(moveY-downY)+circleTop; if(selectflag){ //这里计算的原理和色相条上圆形选择器的位置计算原理是一样的 if(circleNowL>=myCanvas.offsetLeft-circleSelect.offsetWidth/2 &&  circleNowL<=myCanvasWidth+myCanvas.offsetLeft-(circleSelect.offsetWidth/2)-1){  circleSelect.style.left=circleNowL+"px"; } if(circleNowT>=myCanvas.offsetTop-circleSelect.offsetHeight/2  && circleNowT<=myCanvasHeight+myCanvasHeight+myCanvas.offsetTop-(circleSelect.offsetHeight/2)-1){  circleSelect.style.top=circleNowT+"px"; } pickRenderShow(); } })  

4.如果改变RGB和HSL值的任意一个值,那么色相条上的圆形选择器和画布上的圆形选择器的位置都会发生改变,画布颜色,色相条上圆形选择器背景色,颜色展示框的背景色都将发生改变,首先是RGB输入值发生改变:

     //获取输入的RGB值,并作出相应变化var inputNum=[];for(var  j=0;j〈3;j++){input[j].addEventListener("keydown",function(){  setTimeout(function(){  //setTimeout方法暂定,这是为了在键盘按下后,能够更新rgb,获得最新值,从而改变HSL的值,不然键盘按下的一瞬间,获得的数据是上一次的数据;//文本一发生改动,将原先数组的值清空,避免了留下的j变量值,在原有数组的基础上继续添加数组inputNum.splice(0,3);  for(var  i=0;i〈 3;i++){inputNum.push(input[i].value);}  //利用延迟而获得的最新数值,来改变HSL和十六进制if(inputNum[0]〈=255&& inputNum[1]〈=255 && inputNum[2]〈=255){ rgbTOhex(inputNum[0],inputNum[1],inputNum[2]);rgbTOhsl(inputNum[0],inputNum[1],inputNum[2]);var  moveCurrentH=(600*colorh.value)/360-move.offsetHeight/2+bar.offsetTop;//利用返回的HSL中的H值,按照比列来确定move的位置move.style.top=moveCurrentH+"px"; var  imgData=context2.getImageData(0,moveCurrentH-bar.offsetTop+move.offsetHeight/2,1,1); //变化move的背景色//将rgb转为16进制var strHex="#";for(var i=0; i〈3; i++){ var hex = Number(imgData.data[i]).toString(16);if(hex.length===1){hex="0"+hex;}strHex  +=  hex;}  bgcolor=strHex;move.style.backgroundColor=bgcolor; render(bgcolor); //渲染主色板//RGB改变时同时改变渲染板上圆形择色器的位置,根据HSV的原理好定位var max=Math.max(inputNum[0],inputNum[1],inputNum[2]);var min=Math.min(inputNum[0],inputNum[1],inputNum[2]);var V=Number((max/255).toFixed(2));var S=Number(((max-min)/max).toFixed(2));//S的值是画布从左至右,取值为0-1,那么它本身的值可以视为在画布中的一个位置比列,所以要乘以画布的宽,然后减掉它的半径,以圆心为位置,还要加上画布的左边距;同理V的值,只不过V的值是从下开始计算,所以要1减去相应的比例算出相反的比例,才能得出圆形选择器的上偏移量var circleL=S*myCanvasWidth-1-circleSelect.offsetWidth/2+myCanvas.offsetLeft;var circleT=(1-V)*myCanvasHeight-1-circleSelect.offsetHeight/2+myCanvas.offsetTop;circleSelect.style.top=circleT+"px"circleSelect.style.left=circleL+"px"//渲染板上圆形择色器的位置改变时,改变展示板的颜色var context3=show.getContext("2d");context3.fillStyle=colorHex.value;context3.fillRect(0,0,100,100);}else{return;}  },500)  })}

以下是改变HSL值发生的变化:

          //获取输入的HSL值,并作出相应变化var inputHSL=[];for(var  j=3;j〈6;j++){input[j].addEventListener("keydown",function(){setTimeout(function(){inputHSL.splice(0,3); for(var  i=3;i〈 6;i++){inputHSL.push(input[i].value);} if(inputHSL[0]〈=360 &&inputHSL[1]〈=1 && inputHSL[1]〉=0 && inputHSL[2]〈=1 && inputHSL[2]〉=0){hslToRgb(Number(inputHSL[0]),Number(inputHSL[1]),Number(inputHSL[2]));var  moveCurrentH=(600*colorh.value)/360-15+18;move.style.top=moveCurrentH+"px";//变化move位置var  imgData=context2.getImageData(0,moveCurrentH-18+15,1,1); //变化move的背景色var strHex="#";for(var i=0; i〈3; i++){ var hex = Number(imgData.data[i]).toString(16);if(hex.length===1){hex="0"+hex;}strHex  +=  hex;}  bgcolor=strHex;move.style.backgroundColor=bgcolor; render(bgcolor); //渲染主色板//RGB改变时同时改变渲染板上圆形择色器的位置,根据HSV的原理好定位var max=Math.max(colorR.value,colorB.value,colorG.value);var min=Math.min(colorR.value,colorB.value,colorG.value);var V=Number((max/255).toFixed(2));var S=Number(((max-min)/max).toFixed(2));var circleL=S*myCanvasWidth-1-10+18;var circleT=(1-V)*myCanvasHeight-1-10+18;circleSelect.style.top=circleT+"px"circleSelect.style.left=circleL+"px"//渲染板上圆形择色器的位置改变时,改变展示板的颜色var context3=show.getContext("2d");context3.fillStyle=colorHex.value;context3.fillRect(0,0,100,100);}else{return;}  },500);})}

上面rgbTOhex();rgbTOhsl();是转换公式的函数,可以参考上面给出链接,也可以自己上网查,我把js的整个内容都写到html页面中了,在demo中也可以查看转换的函数;
以上就是我的色彩选择器的制作过程,归纳为以下:

  • 色相条的渐变
  • 色相条上圆形选择器的移动导致的:1.圆形选择器背景色的变化。2.画布背景色的渐变(包括饱和度和明度)。3.画布当时圆形选择器中的颜色改变带来的RGB,HSL,颜色展示框的变化。
  • 画布上圆形选择器移动导致的:1.RGB,HSL,十六进制,颜色展示框的变化。2.考虑圆形选择器的位置。
  • RGB输入值的变化导致的:1.HSL,十六进制值变化。2.色相选择器位置和背景色的变化。3.画布上圆形选择器的位置变化。4.颜色展示框的变化。
  • HSL输入值变化导致的:1.RGB,十六进制值变化。2.色相选择器位置和背景色的变化。3.画布上圆形选择器的位置变化。4.颜色展示框的变化。

希望看到这篇文章恰巧又有时间的话,能给我多提提意见,比如我这样写的代码有哪些缺点,这样的方法有哪些缺点,应该用哪种方法更好,因为我只是用我想的方法去实现这样一个功能,没有考虑到其他因素,比如
1.那个setTimeout的方法,我是为了取的当前的值而不是以前的值push到数组中去,我试过,如果发生keydown事件,直接将值push到数组中,是前面的值,不是我当下输入的值,但是我自己也觉得这个方法有点牵强。
2.每次一输入数组的值就得push一遍,是不是一个很麻烦的方法(我找不到其他的词语来形容了),而且为了保证是当前最新的三个数值,我还得将以前的数组清除一遍。。。
非常感谢看完一篇这么啰嗦的文章!!

2017-5-31


色彩选择器(colorPicker)相关推荐

  1. php和android选择器,Android_android 字体颜色选择器(ColorPicker)介绍,primary_text_yellow.xml 复制代码 代 - phpStudy...

    android 字体颜色选择器(ColorPicker)介绍 primary_text_yellow.xml themes.xml @color/primary_text_yellow相关阅读: 在L ...

  2. UWP 颜色选择器(ColorPicker) 和 自定义的Flyout(AdvancedFlyout)

    原文:UWP 颜色选择器(ColorPicker) 和 自定义的Flyout(AdvancedFlyout) ColorPicker 故事背景 项目里面需要一个像Winfrom里面那样的颜色选择器,如 ...

  3. java 选择 颜色的控件_JavaFX颜色选择器(ColorPicker)

    颜色选择器控件允许用户从可用的颜色范围中选择颜色,或通过指定RGB或HSB组合设置其他颜色.JavaFX ColorPicker控件具有颜色选择器,调色板和自定义颜色对话框窗口. 创建ColorPic ...

  4. jQuery颜色选择器ColorPicker

    ColorPicker基于强大的jQuery,使用方便.配置简单,同时不需要加载额外的CSS文件.可以随心所欲的使用到项目中,兼容各大浏览器.效果如下: 代码如下: <!DOCTYPE HTML ...

  5. 练习-原生js写的颜色选择器colorpicker

    colorpicker 文章目录 colorpicker 需求分析: 第一种方案的颜色选择器: 点击色块选择颜色 进行了改进, 把整个颜色选择器封装到js文件里, 通过appendChild的形式添加 ...

  6. 超强的jquery极品插件--色彩选择器类/ 右键菜单类/ 图片新闻flash展示类

    Farbtastic Farbtastic是一个color picker插件.它能够在一个页面中加入多个颜色选择控件,然后每个控件关联到页面中的一个元素比如:文本输入框. Farbtastic jQu ...

  7. 颜色选择器html组件,ColorPicker 颜色选择器

    ColorPicker 颜色选择器 ColorPicker 颜色选择器 用于颜色选择,支持多种格式. 基础用法 有默认值 无默认值 使用 v-model 与 Vue 实例中的一个变量进行双向绑定,绑定 ...

  8. Layui-颜色选择器

    这次介绍layui的颜色选择器colorpicker 模块,使用该模可以在页面加载出一个可以随意选择颜色的组件,下面使用图片给大家演示基础效果 代码内容 页面效果 下面我将介绍基础参数和回调函数,首先 ...

  9. 前端项目一键换肤vue+element(ColorPicker)

    前端项目一键换肤 1.需要配色的都是用变量声明 2.增加颜色选择器 3.改变颜色,更改初始值 1.需要配色的都是用变量声明 /* 全局样式 */ body {// 无需改变--light_color_ ...

最新文章

  1. R语言ggplot2可视化:修改已经创建的ggplot2可视化对象进行自定义的修改、使用ggplot_build函数更改已经创建的可视化结果
  2. mysql棋牌管理_棋牌架构DB服务(Mysql+Redis)数据存储演进笔记
  3. 微软 服务器和工具产品,微软服务器和工具部总裁鲍伯·穆格里亚辞职
  4. printf()详解之终极无惑-转载
  5. IDOC实例,消息方式的IDOC
  6. .jsp页面提交form表单,后台却无法获取input文本框value值
  7. mysql驱动rpm和jar_mysql5.7.11对应的JDBC驱动是哪个版本
  8. 使用Python模拟蒙蒂霍尔悖论游戏
  9. 《ActionScript 3.0基础教程》——2.2 显示队列概述
  10. 复盘图像双线性插值推导细节
  11. Redis 分布式并发防止脏读
  12. HDU2825 Wireless Password【AC自动机 + DP】
  13. 打工人也不好惹!一份校招“恶霸”指南强势冲上GitHub热榜,一天暴涨 1000 星!
  14. HTML+CSS大作业: 抗击疫情网页制作作业_疫情防控网页设计
  15. Android patchrom 流程详解
  16. Vue3中reactive的理解
  17. 一战赚了1090亿,恐怖的张一鸣!
  18. RBCM-PDA-CUR@PLGA红细胞膜包裹聚多巴胺涂覆PLGA/细胞膜包覆纳米拓扑结构阵列
  19. python如何做混合模型面板回归_面板模型回归操作指南,适合初学者!
  20. Elasticsearch实战(十五)---查询query,filter过滤,结合aggs 进行局部/全局聚合统计

热门文章

  1. quest3d通道英汉对照部分
  2. log4j(一)——什么是Log4j以及Log4j的体系结构
  3. 2014年年终总结——获得集团优秀员工称号的心得体会
  4. 百度网盘下载慢怎么解决
  5. Azure | AZ-204 认证之旅-应用服务(一)
  6. 谷歌地图拼接软件_谷歌地图上又有新发现?出现两个长条弧状物体,颜色一白和一黑...
  7. ASP.NET 使用日期控件
  8. css3怎样设置div边框圆角 怎样把div变成圆形
  9. 一分钟教你学会手动提取pdx文件
  10. vuforia ar unity 案例 从零开发 二 扫描图片展示模型