JavaScript调色器以及取互补色的算法思路

时间:2022-02-25 19:00:13

最近用js做了个调色器, 功能和xp自带的调色器一样.

似乎CSDN博客不能跑JS,就发个干巴图上来,可以去alimama发布个广告位看看:).

JavaScript调色器以及取互补色的算法思路

做这个的过程我主要的工作就是上网查寻了色彩模式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度即可

JavaScript调色器以及取互补色的算法思路

对于饱和度就比较麻烦了,饱和度很低的时候大家都灰不垃圾的,

所有最饱和的颜色的反色都是灰色看上去也比较荒唐

但无论怎样就当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;
 }