全国咨询热线:18720358503

答题考试小程序_JavaScript完成HSL拾色器

类别:媒体报道 发布时间:2021-01-05 浏览人次:

JavaScript实现HSL拾色器     -司马懿   这篇文章主要为大家详细介绍了JavaScript实现HSL拾色器,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

HSL 和 HSV 在数学上定义为在 RGB 空间中的颜色的 R, G 和 B 的坐标的变换。

从 RGB 到 HSL 或 HSV 的转换

设 (r, g, b) 分别是一个颜色的红、绿和蓝坐标,它们的值是在 0 到 1 之间的实数。设 max 等价于 r, g 和 b 中的最大者。设 min 等于这些值中的最小者。要找到在 HSL 空间中的 (h, s, l) 值,这里的 h ∈ [0, 360)是角度的色相角,而 s, l ∈ [0,1] 是饱和度和亮度,计算为:

h 的值通常规范化到位于 0 到 360°之间。而 h = 0 用于 max = min 的(就是灰色)时候而不是留下 h 未定义。
HSL 和 HSV 有同样的色相定义,但是其他分量不同。HSV 颜色的 s 和 v 的值定义如下:

从 HSL 到 RGB 的转换

给定 HSL 空间中的 (h, s, l) 值定义的一个颜色,带有 h 在指示色相角度的值域 [0, 360)中,分别表示饱和度和亮度的s 和 l 在值域 [0, 1] 中,相应在 RGB 空间中的 (r, g, b) 三原色,带有分别对应于红色、绿色和蓝色的 r, g 和 b 也在值域 [0, 1] 中,它们可计算为:
首先,如果 s = 0,则结果的颜色是非彩色的、或灰色的。在这个特殊情况,r, g 和 b 都等于 l。注意 h 的值在这种情况下是未定义的。
当 s ≠ 0 的时候,可以使用下列过程:

对于每个颜色向量 Color = (ColorR, ColorG, ColorB) = (r, g, b),

从 HSV 到 RGB 的转换

类似的,给定在 HSV 中 (h, s, v) 值定义的一个颜色,带有如上的 h,和分别表示饱和度和明度的 s 和 v 变化于 0 到 1 之间,在 RGB 空间中对应的 (r, g, b) 三原色可以计算为:

对于每个颜色向量 (r, g, b),

 html 
 style 
 .childDiv {
 display:inline-block; 
 vertical-align:middle;
 margin-left: 30px;
 margin-top: 10px;
 margin-bottom: 10px;
 #colorPickDiv {
 background-color: WhiteSmoke;
 border: 1px solid LightGrey;
 padding-top: 20px;
 padding-bottom: 20px;
 padding-right: 30px;
 #hueTipDiv {
 margin: 0 0 10px 70px;
 #luminanceTipDiv {
 margin-top: 20px
 #colorDiv {
 width: 100px;
 height: 100px;
 background-color: black;
 #valueDiv {
 box-shadow: 0px -5px 10px LightGrey;
 background-color: WhiteSmoke;
 border: 1px solid LightGrey;
 border-top-width: 0;
 padding-right: 10px;
 padding-bottom: 10px;
 /style 
 body 
 div 
 div id="colorPickDiv" 
 div 
 div id="hueTipDiv" Hue:0 /div 
 canvas id="canvas" width="200" height="200" Your browser does not support canvas /canvas 
 /div 
 div 
 div id="saturationTipDiv" Saturation:0% /div 
 input id="saturationRange" onChange="onHSLRangeChange()" type="range" min="0" max="100" step="1" value="100"/ 
 div id="luminanceTipDiv" Luminance:0% /div 
 input id="luminanceRange" onChange="onHSLRangeChange()" type="range" min="0" max="100" step="1" value="50"/ 
 /div 
 div id="colorDiv" /div 
 /div 
 div id="valueDiv" 
 div 
 div id="hexadecimalTipDiv" Hexadecimal: /div 
 input id="hexadecimalValueDiv" type="text" disabled="disabled"/ 
 /div 
 div 
 div id="rgbTipDiv" RGB: /div 
 input id="rgbValueDiv" type="text" readonly="readonly"/ 
 /div 
 div 
 div id="hslTipDiv" HSL: /div 
 input id="hslValueDiv" type="text" readonly="readonly"/ 
 /div 
 /div 
 /div 
 script 
 var c = document.getElementById("canvas");
 var ctx = c.getContext("2d");
 var colorDiv = document.getElementById("colorDiv");
 var hexadecimalValueDiv = document.getElementById("hexadecimalValueDiv");
 var rgbValueDiv = document.getElementById("rgbValueDiv");
 var hslValueDiv = document.getElementById("hslValueDiv");
 var hexadecimalTipDiv = document.getElementById("hexadecimalTipDiv");
 var saturationTipDiv = document.getElementById("saturationTipDiv");
 var saturationRange = document.getElementById("saturationRange");
 var luminanceTipDiv = document.getElementById("luminanceTipDiv");
 var luminanceRange = document.getElementById("luminanceRange");
 //十字光标颜色
 var crossCursorColor = "black";
 //十字光标线宽
 var crossCursorLineWidth = 2;
 //十字光标某一边线段长
 var crossCursorHalfLineLen = 5;
 //十字光标中间断裂处长度
 var crossCursorHalfBreakLineLen = 2;
 //画布中心点X坐标
 var centerX = c.width / 2;
 //画布中心点Y坐标
 var centerY = c.height / 2;
 //缩放绘制比例
 var scaleRate = 10;
 //画布的内切圆半径(之所以减去一个数是为了可以显示完整的十字光标)
 var innerRadius = Math.min(centerX, centerY) - crossCursorHalfLineLen - crossCursorHalfBreakLineLen;
 //内切圆半径的平方
 var pow2InnerRadius = Math.pow(innerRadius, 2);
 //缩放绘制时的绘制半径,即画布的外径除以缩放比例
 var scaledRadius = Math.sqrt(Math.pow(c.width / 2, 2) + Math.pow(c.height / 2, 2)) / scaleRate;
 //由于该圆是由绕圆心的多条线段组成,该值表示将圆分割的份数
 var count = 360;
 //一整个圆的弧度值
 var doublePI = Math.PI * 2;
 //由于圆心处是多条线段的交汇点,Composite是source-over模式,所以后绘制的线段会覆盖前一个线段。另外由于采用线段模拟圆,英雌
 var deprecatedRadius = innerRadius * 0.3;
 //废弃圆半径的平方
 var pow2DeprecatedRadius = Math.pow(deprecatedRadius, 2);
 //色相(0-360)
 var hue;
 //饱和度(0%-100%)
 var saturation; 
 //亮度luminance或明度lightness(0%-100%)
 var luminance;
 //当前色相位置X坐标
 var currentHuePosX = centerX + innerRadius - 1;
 //当前色相位置Y坐标
 var currentHuePosY = centerY;
 //填充圆
 function fillCircle(cx, cy, r, color) {
 ctx.fillStyle = color;
 ctx.beginPath();
 ctx.arc(cx, cy, r, 0, doublePI);
 ctx.fill();
 //绘制线条
 function strokeLine(x1, y1, x2, y2) {
 ctx.beginPath();
 ctx.moveTo(x1, y1);
 ctx.lineTo(x2, y2);
 ctx.stroke();
 //将整数转为16进制,至少保留2位
 function toHexString(intValue) {
 var str = intValue.toString(16);
 if(str.length == 1) {
 str = "0" + str;
 return str;
 //判断坐标(x,y)是否在合法的区域内
 function isInValidRange(x, y) {
 var pow2Distance = Math.pow(x-centerX, 2) + Math.pow(y-centerY, 2);
 return pow2Distance = pow2DeprecatedRadius pow2Distance = pow2InnerRadius;
 //绘制十字光标
 function strokeCrossCursor(x, y) {
 ctx.globalCompositeOperation = "source-over";
 ctx.strokeColor = crossCursorColor;
 ctx.lineWidth = crossCursorLineWidth;
 strokeLine(x, y-crossCursorHalfBreakLineLen, x, y-crossCursorHalfBreakLineLen-crossCursorHalfLineLen);
 strokeLine(x, y+crossCursorHalfBreakLineLen, x, y+crossCursorHalfBreakLineLen+crossCursorHalfLineLen);
 strokeLine(x-crossCursorHalfBreakLineLen, y, x-crossCursorHalfBreakLineLen-crossCursorHalfLineLen, y);
 strokeLine(x+crossCursorHalfBreakLineLen, y, x+crossCursorHalfBreakLineLen+crossCursorHalfLineLen, y);
 //将对象中的hsl分量组成一个hsl颜色(h在0到360之间,s与l均在0到1之间)
 function formHslColor(obj) {
 return "hsl(" + obj.h + "," + Math.round(obj.s * 1000)/10 + "%," + Math.round(obj.l * 1000)/10 + "%)"; 
 //将对象中的rgb分量组成一个rgb颜色(r,g,b在0到255之间)
 function formRgbColor(obj) {
 return "rgb(" + [obj.r, obj.g, obj.b].join(",") + ")";
 //从画布的某点获取存储RGB的对象
 function getRgbObj(x, y) {
 var w = 1;
 var h = 1;
 var imgData = ctx.getImageData(x,y,w,h);
 var obj = {
 r: imgData.data[0],
 g: imgData.data[1],
 b: imgData.data[2],
 a: imgData.data[3]
 return obj;
 //将rgb转换为hsl对象()
 function rgbToHslObj(r, g, b) {
 r /= 255;
 g /= 255;
 b /= 255;
 var max = Math.max(r, g, b);
 var min = Math.min(r, g, b);
 var diff = max - min;
 var twoValue = max + min;
 var obj = {h:0, s:0, l:0};
 if(max == min) {
 obj.h = 0;
 } else if(max == r g = b) {
 obj.h = 60 * (g - b) / diff;
 } else if(max == r g b) {
 obj.h = 60 * (g - b) / diff + 360;
 } else if(max == g) {
 obj.h = 60 * (b - r) / diff + 120;
 } else if(max == b) {
 obj.h = 60 * (r - g) / diff + 240;
 obj.l = twoValue / 2;
 if(obj.l == 0 || max == min) {
 obj.s = 0;
 } else if(0 obj.l obj.l = 0.5) {
 obj.s = diff / twoValue;
 //obj.s = diff / (2 * obj.l);
 } else {
 obj.s = diff / (2 - twoValue);
 //obj.s = diff / (2 - 2 * obj.l);
 obj.h = Math.round(obj.h);
 return obj;
 //创建Hue颜色圆环
 function createHueRing() {
 ctx.globalCompositeOperation = "source-over";
 ctx.clearRect(0,0,c.width,c.height);
 ctx.save();
 //将绘制原点移动到画布中心
 ctx.translate(centerX, centerY);
 //将画布放大相应比例,restore后,绘制内容会缩小
 ctx.scale(scaleRate, scaleRate);
 for(var i=0; i count; i++) {
 var degree = i / count * 360;
 var radian = Math.PI * degree / 180;
 var x = scaledRadius * Math.cos(radian);
 var y = scaledRadius * Math.sin(radian);
 ctx.lineWidth=1;
 ctx.strokeStyle = "hsl(" + degree +"," + saturation + "," + luminance + ")";
 ctx.beginPath();
 ctx.moveTo(x, y);
 ctx.lineTo(0,0);
 ctx.stroke();
 ctx.restore();
 ctx.globalCompositeOperation = "destination-out";
 fillCircle(centerX, centerY, deprecatedRadius, "black");
 ctx.globalCompositeOperation = "destination-in";
 fillCircle(centerX, centerY, innerRadius, "black");
 //点击canvas中的Hue拾色圈
 function onCanvasClick() {
 var x = event.offsetX;
 var y = event.offsetY;
 if(!isInValidRange(x, y)) {
 return;
 currentHuePosX = x;
 currentHuePosY = y;
 //创建hue背景圆环
 createHueRing();
 setColorValue(x, y);
 strokeCrossCursor(x, y);
 function setColorValue(x, y) {
 //获取包含rgb的颜色对象
 var rgbObj = getRgbObj(x, y);
 var rgbColor = formRgbColor(rgbObj);
 colorDiv.style.backgroundColor = rgbColor;
 rgbValueDiv.value = rgbColor;
 var hex = "#" + toHexString(rgbObj.r) + toHexString(rgbObj.g) + toHexString(rgbObj.b);
 hexadecimalValueDiv.value = hex;
 var hslObj = rgbToHslObj(rgbObj.r, rgbObj.g, rgbObj.b);
 hslValueDiv.value = formHslColor(hslObj);
 hueTipDiv.innerHTML = ("Hue:" + hslObj.h);
 function onHSLRangeChange() {
 //event.target.value;
 saturation = saturationRange.value + "%";
 luminance = luminanceRange.value + "%";
 saturationTipDiv.innerHTML = ("Saturation:" + saturation);
 luminanceTipDiv.innerHTML = ("Luminance:" + luminance);
 createHueRing();
 setColorValue(currentHuePosX, currentHuePosY)
 strokeCrossCursor(currentHuePosX, currentHuePosY);
 function init() {
 c.addEventListener("click", onCanvasClick);
 onHSLRangeChange();
 init();
 /script 
 /body 
 /html 

有几个缺陷:

- 不能根据颜色值来设置HSL。
- 由于HSL的值是根据从Hue环形调色板中取出的RGB颜色值换算为HSL的,因此跟滑动条上的值可能会有出入(如果是5舍6入那就一样了)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持凡科。


推荐阅读

聊城市网站建设难-酒店型的网站该如何做?酒店

新建设酒店餐厅网站时大家要充足考虑到“酒店餐厅”的运营服务特点 因而大家在制作计划方案时候重视系统软件的好用性 靠谱性 优秀性和经济发展性标准 此外还会继续留意系统软件...

2021-01-15
网站建站公司-规范而标准的流程是保证企业网站

创建一个网站并不是一件简易的事儿。尽管一些企业如今投放广告说她们只花好几百元就可以建一个网站,可是在它的身后有许多掩藏的难题。数100元的网站并不是自身设计方案的,但...

2021-01-15
企业商城建站套餐-一个阿里云域名站应当如何建

制作一个网站是非常容易的,而想要运营好一个网站就非常难。建站行业发展迅速,近几年出现了很多建站公司,而成功发展下来的又有多少呢?在一开始都是模仿,然后不断创新,慢...

2021-01-14
网页模板图片-万象云模板自助建站系统系统201

微信小程序1.增加查寻作用应用情景:公司会出现一些和本身业务流程有关的数据信息,必须给到顾客出示“查寻信息内容”或“查寻交费”服务。1)查寻信息内容:院校、学习培训组...

2021-01-14
广州凡科互联网科技股份有限公司招聘电商网络

招聘人数:23职位信息如果你拥有强大的企图心和追求理想的韧性来吧,这里,给你的不仅是一份养家糊口的工作,而是一份事业!这里,你不仅仅是一个普通的销售,而是一个想要成功...

2021-01-13
广州凡科互联网科技股份有限公司招聘财务出纳

招聘人数:7职位信息岗位职责:1、日常现金、银行、票据的收、支结算;2、登记现金、银行日记账,对各类票据做好备查登记;3、每日核对现金、银行余额,编制资金日报表;4、对各...

2021-01-13
X

400-8700-61718720358503
企业邮箱2639601583@qq.com
官方微信