[백업][가리사니] html 컬러피커를 만들어보자
html, javascript
이 문서는 가리사니 개발자 포럼에 올렸던 글의 백업 파일입니다. 오래된 문서가 많아 현재 상황과 맞지 않을 수 있습니다.
만들고 싶었던 스타일의 컬러피커는 HSL and HSV 의 어도비 스타일로 우선 오른쪽 바가 어떤형태로 작동하는지 알아야 했습니다.
1. 어도비스타일 컬러피커
[https://www.google.ca/search?q=photoshop+color+tool&tbm=isch 필자가 만들고 싶었던건 위 어도비 스타일의 컬러피커 입니다.
2. 오른쪽 무지개바?
필자는 처음에 저게 무슨 규칙으로 놓여저 있는지 알수가 없어서 위키백과를 찾아보던 도중.. 아래와 같은 문서를 보게되었습니다. [https://en.wikipedia.org/wiki/HSL_and_HSV 위 문서를 참고해보면 가시광선 스펙트럼의 적[빨강] -> 자[보라]를 뒤집어놓은 형태에서 눈에 보이지 않는 자외선이 자리잡아야할 공간에 다시 적색이 회귀하는 특이한 형태입니다.
특징
- 가시광선 스펙트럼이 뒤집어진 형태 자외선 부분이 다시 적색으로 회귀하고 있다.
3. 왼쪽에 파렛트
좌상단 : 흰색 FFFFFF 우상단 : 색상바에서 선택된 색상 하단(공통) : 검정색 이러한 특이한 형태를 하고 있습니다. 규칙 2~3
- x방향 : 흰색 -> 선택된색까지의 그라데이션
- y방향 : R, G, B 각각의 색상(0~255)이 0에 수렴할때까지 1픽셀당 1씩 떨어진다.
4. 규칙정리
- 가시광선 스펙트럼이 뒤집어진 형태 자외선 부분이 다시 적색으로 회귀하고 있다. 이걸 구현하기위해선 스펙트럼의 특성을 알아야하지만, 각 색의 최대치와 최소치가 변하는 부분만 찾아서 그라데이션으로 구현하기로 했습니다. 그래서 찾아낸 최대치와 최소치가 되는 지점입니다. ff 00 00 - 빨강색 ff 00 ff - 보라색 00 00 ff - 파랑색 00 ff ff - 하늘색 00 ff 00 - 초록색 ff ff 00 - [색상 ff0]노랑색 ff 00 00 - 빨강색 주) 자스로 한색상마다 찍어주는경우 시간소모가 크기때문에 그라데이션 기능을 쓰기로했습니다. 필자의 컴퓨터로 1픽셀씩 찍었을경우 0.250 초 그라데이션을 썼을경우 0.008 초 걸렸습니다.
- x방향 : 흰색 -> 선택된색까지의 그라데이션
- y방향 : R, G, B 각각의 색상(0~255)이 0에 수렴할때까지 1픽셀당 1씩 떨어진다. 사실 이건 따로 설명할 필요가 없을정도로 간단합니다. 좌우 그라데이션을 0xFF ~ 지정된색 까지 주고 아래로는 if (r > 0) { r–; } 같은 방법으로 g b 이렇게 처리하면됩니다.
5. 구현
자료정리가 끝났으니 가볍게(?) 구현해봤습니다. 시간관계상 간단하게만 만들어봤습니다. 오른쪽의 스팩트럼을 누르면 표시됩니다. mousedown, mousemove, mouseup 을 함께써서 포토샵처럼 끌면서 볼수있도록 업그레이드 시켜보세요…
<html>
<head>
<script type="text/javascript">
// 2015-09-06 박용서 : 작성
// [/2015/09/06/%EB%B0%B1%EC%97%85-%EA%B0%80%EB%A6%AC%EC%82%AC%EB%8B%88-HTML-%EC%BB%AC%EB%9F%AC%ED%94%BC%EC%BB%A4%EB%A5%BC-%EB%A7%8C%EB%93%A4%EC%96%B4%EB%B3%B4%EC%9E%90.html](/2015/09/06/%EB%B0%B1%EC%97%85-%EA%B0%80%EB%A6%AC%EC%82%AC%EB%8B%88-HTML-%EC%BB%AC%EB%9F%AC%ED%94%BC%EC%BB%A4%EB%A5%BC-%EB%A7%8C%EB%93%A4%EC%96%B4%EB%B3%B4%EC%9E%90.html)
var cp = {
bar : null, // color bar
barc : null, // color bar context
pal : null, // palette
palc : null, // palette context
pallc : null, // palette last color
// 초기화
init : function() {
// 오른쪽 바를 새로고침한다.
cp.initBar();
// 팔렛트를 초기화한다.
cp.initPalette();
// 기본값 : 빨강색 선택
cp.drawPalette(255, 0, 0);
},
// 색상바 초기화
initBar : function() {
var bar = cp.bar = document.getElementById('bar');
var ctx = cp.barc = bar.getContext('2d');
// 처음 크기가 멋대로 잡혀있다. (초기화)
// ignore css?? init resize..;;
var w = bar.width = 20;
var h = bar.height = 256;
// 그라디언트를 불러온다.
var grd = ctx.createLinearGradient(0,0,w,h);
grd.addColorStop(0,'#ff0000');
grd.addColorStop(0.166,'#ff00ff');
grd.addColorStop(0.333,'#0000ff');
grd.addColorStop(0.5,'#00ffff');
grd.addColorStop(0.666,'#00ff00');
grd.addColorStop(0.834,'#ffff00');
grd.addColorStop(1,'#ff0000');
// 지정한 그라데이션을 그린다.
ctx.fillStyle = grd;
ctx.fillRect(0, 0, w, h);
bar.onclick = function(e) {
// y 좌표를 가져온다.
var y = e.pageY - cp.bar.offsetTop;
// 해당 위치의 색상을 가져온다.
var c = cp.barc.getImageData(0, y, 1, 1).data;
// r g b 순서대로 부른다.
cp.drawPalette(c[0], c[1], c[2]);
};
},
// 팔렛트를 초기화한다.
initPalette : function() {
var pal = cp.pal = document.getElementById('palette');
cp.palc = pal.getContext('2d');
// 이유는 모르겠지만.. 크기가 이상해서 다시 잡아준다.
pal.width = 256;
pal.height = 256;
},
// 팔렛트를 그린다.
drawPalette : function(r, g, b) {
// 마지막으로 선택된 컬러와 같다면 자원을 아까기위해 스킵한다.
var nowColor = (r+'-'+g+'-'+b);
if (cp.pallc == nowColor) { return; } else { cp.pallc = nowColor; }
// 팔렛트의 컨텍스를 가져옴
var palc = cp.palc;
// 위에서부터 1픽셀씩 내려오면서 그림
for (i = 0; i < 255; )
{
var leftColor = 255 - i; // 왼쪽 [상 -> 하] 명도 계산!
// 그리기
var grd = palc.createLinearGradient(0, 0, 256, 1);
grd.addColorStop(0,'rgb('+leftColor+', '+leftColor+', '+leftColor+')');
grd.addColorStop(1,'rgb('+r+', '+g+', '+b+')');
palc.fillStyle = grd;
palc.fillRect(0, i++, 256, i);
// 위 설명대로 루프당 명도를 1씩 떨어뜨립니다.
if (r > 0) { r--; }
if (g > 0) { g--; }
if (b > 0) { b--; }
}
}
};
</script>
<style>
#palette { width:256px; height:256px; }
#bar { width:20px; height:256px; }
</style>
</head>
<body onload="cp.init();">
<canvas id="palette"></canvas>
<canvas id="bar"></canvas>
</body>
</html>