JavaScript HSL 픽업 실현
RGB 에서 HSL 또는 HSV 로 의 전환
설정(r,g,b)은 각각 색깔 의 빨간색,녹색,파란색 좌표 이 고 그들의 값 은 0 에서 1 사이 의 실수 이다.max 등가 r,g,b 의 최대 자 를 설정 합 니 다.min 을 설정 하면 이 값 중 가장 작은 것 입 니 다.HSL 공간 에서(h,s,l)값 을 찾 으 려 면 여기 h*8712°0,360)은 각도 의 색상 각 이 고 s,l*8712°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)3 원색 으로 빨간색,녹색 과 파란색 에 대응 하 는 r,g 와 b 도 값 영역[0,1]에서 계산 할 수 있 습 니 다.
우선,s=0 이면 결 과 는 비 컬러 또는 회색 입 니 다.이 특수 한 상황 에서 r,g,b 는 모두 l 과 같다.이 경우 h 의 값 이 정의 되 지 않 았 음 을 주의 하 십시오.
s≠0 일 때 다음 과정 을 사용 할 수 있다.
색상 별 벡터 색상=(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 class="childDiv">
<div id="hueTipDiv">Hue:0</div>
<canvas id="canvas" width="200" height="200">Your browser does not support canvas</canvas>
</div>
<div class="childDiv">
<div id="saturationTipDiv" class="divMarginBottom">Saturation:0%</div>
<input id="saturationRange" onChange="onHSLRangeChange()" type="range" min="0" max="100" step="1" value="100"/>
<div id="luminanceTipDiv" class="divMarginBottom">Luminance:0%</div>
<input id="luminanceRange" onChange="onHSLRangeChange()" type="range" min="0" max="100" step="1" value="50"/>
</div>
<div id="colorDiv" class="childDiv"></div>
</div>
<div id="valueDiv">
<div class="childDiv">
<div id="hexadecimalTipDiv" class="divMarginBottom">Hexadecimal:</div>
<input id="hexadecimalValueDiv" type="text" disabled="disabled"/>
</div>
<div class="childDiv">
<div id="rgbTipDiv" class="divMarginBottom">RGB:</div>
<input id="rgbValueDiv" type="text" readonly="readonly"/>
</div>
<div class="childDiv">
<div id="hslTipDiv" class="divMarginBottom">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 입 이면 마찬가지)
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[2022.04.19] 자바스크립트 this - 생성자 함수와 이벤트리스너에서의 this18일에 this에 대해 공부하면서 적었던 일반적인 함수나 객체에서의 this가 아닌 오늘은 이벤트리스너와 생성자 함수 안에서의 this를 살펴보기로 했다. new 키워드를 붙여 함수를 생성자로 사용할 때 this는...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.