JavaScript調色器以及取互補色的算法思路

id="alimamaifrm" border="0" name="alimamaifrm" marginwidth="0" marginheight="0" src="http://p.alimama.com/code.php?t=2&i=mm_10003521_106784_109301&w=760&h=90&sz=11&bgc=FFFACD&bdc=FFFFFF&tc=000080&lc=000000&dc=000000" scrolling="no" width="760" frameborder="0" height="90">

最近用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;
 }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章