最近用js做了個調色器, 功能和xp自帶的調色器一樣.
似乎CSDN博客不能跑JS,就發個乾巴圖上來,可以去alimama發佈個廣告位看看:).
做這個的過程我主要的工作就是上網查尋了色彩模式HSB(有的地方叫HSL)和RGB的轉換算法
最終我找到了顏色方面的算法大全 http://www.easyrgb.com/math.php?MATH=M18#text18
老外還是有一套,這裏有幾乎所有顏色模式之間相互轉換的代碼XYZ,Yxy,Hunter-Lab,CIE-L*ab,CIE-L*CH°,CIE-L*uv,CMY,CMYk,HSV等等,基本上我都不知道是什麼模式,那是另一門學問,
爲什麼要H(色調)S(飽和度)L(亮度)和R(紅色)G(綠色)B(藍色)的轉換呢,因爲如上圖,x軸表示色調,y軸表示飽和度,階梯則表示確定了色調和飽和度之後,不同亮度時我們得到的顏色.
所以找到了HSL到RGB的轉換算法,其他拖拖拽拽,晃晃點點都是JavaScript的常用伎倆了.
這裏也想到了另一個問題,取反色,或者取互補色,如何得到和一種顏色的反差最大的顏色.
網上一搜不知哪個天才設計的算法用rgb的每個255一減當前值得到差就是了,可不黑對白,白對黑豈知128算出的是127
關於這個問題easyrgb這個網站上有沒有算法我還不知道,無奈英文太差
至少以HSL色彩模式來看待顏色取反時H和L會有比較清晰的思路
對於亮度0對1 0.5對0.5
對於色調它形成的是一個色環,只要在環上轉180度即可
對於飽和度就比較麻煩了,飽和度很低的時候大家都灰不垃圾的,
所有最飽和的顏色的反色都是灰色看上去也比較荒唐
但無論怎樣就當S值不變,HL取反得到的結果對於大多數顏色而言反差還是夠大的,畢竟如果沒有基於算法的顏色取反的定義,我們的需求一般只是要有一定的反差,避免字和底色太相近結果什麼都看不清而已
最後突然一個想法,現在的框架是越來越多了,百家爭鳴,萬馬奇諳,以後做些看來要不只要有個標籤"跨瀏覽器"還要"跨前端框架"了,不然爲了小東西你本來是jquery的,非要引入個dojo,豈不麻煩透了.呵呵
說白了就是純JavaScript吧,各種框架把js打扮的越來越像java像perl.當然是好事
可到最後當我們還區分不開DOM和BOM,區分不開Arrry和window的時候,就已經跨越到區分不開prototype和prototype.js,不知道js有沒有trim()的另一個層次了.是否也算一種悲哀.
附翻譯成js的rgb<->hsl轉換算法
rgb取值範圍(0-255),hsl取值範圍成(0-240)(和windows保持一致)
function rgb2hsl(rgb){
var hsl={};
var H,S,L;
var r = rgb.r/255;
var g = rgb.g/255;
var b = rgb.b/255;
var vmin = (r<((g<b)?g:b))?r:((g<b)?g:b);
var vmax = (r>((g>b)?g:b))?r:((g>b)?g:b);
var del = vmax-vmin;
var L = (vmax+vmin)/2;
if(del==0){
H = 0;
S = 0;
}else{
if(L<0.5){
S = del/(2*L)
}else{
S = del/(2-2*L)
}
dr = (((vmax-r)/6)+(del/2))/del;
dg = (((vmax-g)/6)+(del/2))/del;
db = (((vmax-b)/6)+(del/2))/del;
if(r==vmax){
H = db-dg;
}else if(g==vmax){
H = (1/3)+dr-db;
}else if(b==vmax){
H = (2/3)+dg-dr;
}
if(H<0)H+=1;
if(H>1)H-=1;
}
hsl.h = Math.round(H*240);
hsl.s = Math.round(S*240);
hsl.l = Math.round(L*240);
return hsl;
}
function hsl2rgb(hsl){
function h2rgb(v1,v2,vH){
if(vH<0)vH += 1;
if(vH>1)vH -= 1;
if((6*vH)<1)return(v1+(v2-v1)*6* vH );
if((2*vH)<1)return(v2);
if((3*vH)<2)return(v1+(v2-v1)*((2/3)-vH)*6);
return v1;
}
var rgb = {};
var H = hsl.h/240;
var S = hsl.s/240;
var L = hsl.l/240;
if(S==0){
rgb.r = Math.round(L*225);
rgb.g = Math.round(L*225);
rgb.b = Math.round(L*225);
}else{
var v1,v2;
if(L<0.5){
v2 = L*(1+S);
}else{
v2 = (L+S)-(S*L);
}
v1 = 2*L-v2;
rgb.r = Math.round(255*h2rgb(v1,v2,H+(1/3)));
rgb.g = Math.round(255*h2rgb(v1,v2,H));
rgb.b = Math.round(255*h2rgb(v1,v2,H-(1/3)));
}
return rgb;
}