/public/javascripts/dojo/release/dojo/dojox/color/Palette.js

http://enginey.googlecode.com/ · JavaScript · 386 lines · 281 code · 36 blank · 69 comment · 35 complexity · b9360cb3620de4360190422a8b1c4ca3 MD5 · raw file

  1. /*
  2. Copyright (c) 2004-2008, The Dojo Foundation All Rights Reserved.
  3. Available via Academic Free License >= 2.1 OR the modified BSD license.
  4. see: http://dojotoolkit.org/license for details
  5. */
  6. if(!dojo._hasResource["dojox.color.Palette"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
  7. dojo._hasResource["dojox.color.Palette"] = true;
  8. dojo.provide("dojox.color.Palette");
  9. dojo.require("dojox.color");
  10. (function(){
  11. var dxc = dojox.color;
  12. /***************************************************************
  13. * dojox.color.Palette
  14. *
  15. * The Palette object is loosely based on the color palettes
  16. * at Kuler (http://kuler.adobe.com). They are 5 color palettes
  17. * with the base color considered to be the third color in the
  18. * palette (for generation purposes).
  19. *
  20. * Palettes can be generated from well-known algorithms or they
  21. * can be manually created by passing an array to the constructor.
  22. *
  23. * Palettes can be transformed, using a set of specific params
  24. * similar to the way shapes can be transformed with dojox.gfx.
  25. * However, unlike with transformations in dojox.gfx, transforming
  26. * a palette will return you a new Palette object, in effect
  27. * a clone of the original.
  28. ***************************************************************/
  29. // ctor ----------------------------------------------------------------------------
  30. dxc.Palette = function(/* String|Array|dojox.color.Color|dojox.color.Palette */base){
  31. // summary
  32. // An object that represents a palette of colors.
  33. // description
  34. // A Palette is a representation of a set of colors. While the standard
  35. // number of colors contained in a palette is 5, it can really handle any
  36. // number of colors.
  37. //
  38. // A palette is useful for the ability to transform all the colors in it
  39. // using a simple object-based approach. In addition, you can generate
  40. // palettes using dojox.color.Palette.generate; these generated palettes
  41. // are based on the palette generators at http://kuler.adobe.com.
  42. //
  43. // colors: dojox.color.Color[]
  44. // The actual color references in this palette.
  45. this.colors = [];
  46. if(base instanceof dojox.color.Palette){
  47. this.colors = base.colors.slice(0);
  48. }
  49. else if(base instanceof dojox.color.Color){
  50. this.colors = [ null, null, base, null, null ];
  51. }
  52. else if(dojo.isArray(base)){
  53. this.colors = dojo.map(base.slice(0), function(item){
  54. if(dojo.isString(item)){ return new dojox.color.Color(item); }
  55. return item;
  56. });
  57. }
  58. else if (dojo.isString(base)){
  59. this.colors = [ null, null, new dojox.color.Color(base), null, null ];
  60. }
  61. }
  62. // private functions ---------------------------------------------------------------
  63. // transformations
  64. function tRGBA(p, param, val){
  65. var ret = new dojox.color.Palette();
  66. ret.colors = [];
  67. dojo.forEach(p.colors, function(item){
  68. var r=(param=="dr")?item.r+val:item.r,
  69. g=(param=="dg")?item.g+val:item.g,
  70. b=(param=="db")?item.b+val:item.b,
  71. a=(param=="da")?item.a+val:item.a
  72. ret.colors.push(new dojox.color.Color({
  73. r: Math.min(255, Math.max(0, r)),
  74. g: Math.min(255, Math.max(0, g)),
  75. b: Math.min(255, Math.max(0, b)),
  76. a: Math.min(1, Math.max(0, a))
  77. }));
  78. });
  79. console.log("The return colors are ", ret.colors, " from the original colors ", p.colors);
  80. return ret;
  81. }
  82. function tCMY(p, param, val){
  83. var ret = new dojox.color.Palette();
  84. ret.colors = [];
  85. dojo.forEach(p.colors, function(item){
  86. var o=item.toCmy(),
  87. c=(param=="dc")?o.c+val:o.c,
  88. m=(param=="dm")?o.m+val:o.m,
  89. y=(param=="dy")?o.y+val:o.y;
  90. ret.colors.push(dojox.color.fromCmy(
  91. Math.min(100, Math.max(0, c)),
  92. Math.min(100, Math.max(0, m)),
  93. Math.min(100, Math.max(0, y))
  94. ));
  95. });
  96. return ret;
  97. }
  98. function tCMYK(p, param, val){
  99. var ret = new dojox.color.Palette();
  100. ret.colors = [];
  101. dojo.forEach(p.colors, function(item){
  102. var o=item.toCmyk(),
  103. c=(param=="dc")?o.c+val:o.c,
  104. m=(param=="dm")?o.m+val:o.m,
  105. y=(param=="dy")?o.y+val:o.y,
  106. k=(param=="dk")?o.b+val:o.b;
  107. ret.colors.push(dojox.color.fromCmyk(
  108. Math.min(100, Math.max(0, c)),
  109. Math.min(100, Math.max(0, m)),
  110. Math.min(100, Math.max(0, y)),
  111. Math.min(100, Math.max(0, k))
  112. ));
  113. });
  114. return ret;
  115. }
  116. function tHSL(p, param, val){
  117. var ret = new dojox.color.Palette();
  118. ret.colors = [];
  119. dojo.forEach(p.colors, function(item){
  120. var o=item.toHsl(),
  121. h=(param=="dh")?o.h+val:o.h,
  122. s=(param=="ds")?o.s+val:o.s,
  123. l=(param=="dl")?o.l+val:o.l;
  124. ret.colors.push(dojox.color.fromHsl(h%360, Math.min(100, Math.max(0, s)), Math.min(100, Math.max(0, l))));
  125. });
  126. return ret;
  127. }
  128. function tHSV(p, param, val){
  129. var ret = new dojox.color.Palette();
  130. ret.colors = [];
  131. dojo.forEach(p.colors, function(item){
  132. var o=item.toHsv(),
  133. h=(param=="dh")?o.h+val:o.h,
  134. s=(param=="ds")?o.s+val:o.s,
  135. v=(param=="dv")?o.v+val:o.v;
  136. ret.colors.push(dojox.color.fromHsv(h%360, Math.min(100, Math.max(0, s)), Math.min(100, Math.max(0, v))));
  137. });
  138. return ret;
  139. }
  140. // helper functions
  141. function rangeDiff(val, low, high){
  142. // given the value in a range from 0 to high, find the equiv
  143. // using the range low to high.
  144. return high-((high-val)*((high-low)/high));
  145. }
  146. // object methods ---------------------------------------------------------------
  147. dojo.extend(dxc.Palette, {
  148. transform: function(/* Object */kwArgs){
  149. // summary
  150. // Transform the palette using a specific transformation function
  151. // and a set of transformation parameters.
  152. // description
  153. // {palette}.transform is a simple way to uniformly transform
  154. // all of the colors in a palette using any of 5 formulae:
  155. // RGBA, HSL, HSV, CMYK or CMY.
  156. //
  157. // Once the forumula to be used is determined, you can pass any
  158. // number of parameters based on the formula "d"[param]; for instance,
  159. // { use: "rgba", dr: 20, dg: -50 } will take all of the colors in
  160. // palette, add 20 to the R value and subtract 50 from the G value.
  161. //
  162. // Unlike other types of transformations, transform does *not* alter
  163. // the original palette but will instead return a new one.
  164. var fn=tRGBA; // the default transform function.
  165. if(kwArgs.use){
  166. // we are being specific about the algo we want to use.
  167. var use=kwArgs.use.toLowerCase();
  168. if(use.indexOf("hs")==0){
  169. if(use.charAt(2)=="l"){ fn=tHSL; }
  170. else { fn=tHSV; }
  171. }
  172. else if(use.indexOf("cmy")==0){
  173. if(use.charAt(3)=="k"){ fn=tCMYK; }
  174. else { fn=tCMY; }
  175. }
  176. }
  177. // try to guess the best choice.
  178. else if("dc" in kwArgs || "dm" in kwArgs || "dy" in kwArgs){
  179. if("dk" in kwArgs){ fn = tCMYK; }
  180. else { fn = tCMY; }
  181. }
  182. else if("dh" in kwArgs || "ds" in kwArgs){
  183. if("dv" in kwArgs){ fn = tHSV; }
  184. else { fn = tHSL; }
  185. }
  186. var palette = this;
  187. for(var p in kwArgs){
  188. // ignore use
  189. if(p=="use"){ continue; }
  190. palette = fn(palette, p, kwArgs[p]);
  191. }
  192. return palette; // dojox.color.Palette
  193. },
  194. clone: function(){
  195. // summary
  196. // Clones the current palette.
  197. return new dxc.Palette(this); // dojox.color.Palette
  198. }
  199. });
  200. // static methods ---------------------------------------------------------------
  201. dojo.mixin(dxc.Palette, {
  202. generators: {
  203. analogous:function(/* Object */args){
  204. var high=args.high||60, // delta between base hue and highest hue (subtracted from base)
  205. low=args.low||18, // delta between base hue and lowest hue (added to base)
  206. base = dojo.isString(args.base)?new dojox.color.Color(args.base):args.base,
  207. hsv=base.toHsv();
  208. // generate our hue angle differences
  209. var h=[
  210. (hsv.h+low+360)%360,
  211. (hsv.h+Math.round(low/2)+360)%360,
  212. hsv.h,
  213. (hsv.h-Math.round(high/2)+360)%360,
  214. (hsv.h-high+360)%360
  215. ];
  216. var s1=Math.max(10, (hsv.s<=95)?hsv.s+5:(100-(hsv.s-95))),
  217. s2=(hsv.s>1)?hsv.s-1:21-hsv.s,
  218. v1=(hsv.v>=92)?hsv.v-9:Math.max(hsv.v+9, 20),
  219. v2=(hsv.v<=90)?Math.max(hsv.v+5, 20):(95+Math.ceil((hsv.v-90)/2)),
  220. s=[ s1, s2, hsv.s, s1, s1 ],
  221. v=[ v1, v2, hsv.v, v1, v2 ]
  222. return new dxc.Palette(dojo.map(h, function(hue, i){
  223. return dojox.color.fromHsv(hue, s[i], v[i]);
  224. })); // dojox.color.Palette
  225. },
  226. monochromatic: function(/* Object */args){
  227. var base = dojo.isString(args.base)?new dojox.color.Color(args.base):args.base,
  228. hsv = base.toHsv();
  229. // figure out the saturation and value
  230. var s1 = (hsv.s-30>9)?hsv.s-30:hsv.s+30,
  231. s2 = hsv.s,
  232. v1 = rangeDiff(hsv.v, 20, 100),
  233. v2 = (hsv.v-20>20)?hsv.v-20:hsv.v+60,
  234. v3 = (hsv.v-50>20)?hsv.v-50:hsv.v+30;
  235. return new dxc.Palette([
  236. dojox.color.fromHsv(hsv.h, s1, v1),
  237. dojox.color.fromHsv(hsv.h, s2, v3),
  238. base,
  239. dojox.color.fromHsv(hsv.h, s1, v3),
  240. dojox.color.fromHsv(hsv.h, s2, v2)
  241. ]); // dojox.color.Palette
  242. },
  243. triadic: function(/* Object */args){
  244. var base = dojo.isString(args.base)?new dojox.color.Color(args.base):args.base,
  245. hsv = base.toHsv();
  246. var h1 = (hsv.h+57+360)%360,
  247. h2 = (hsv.h-157+360)%360,
  248. s1 = (hsv.s>20)?hsv.s-10:hsv.s+10,
  249. s2 = (hsv.s>90)?hsv.s-10:hsv.s+10,
  250. s3 = (hsv.s>95)?hsv.s-5:hsv.s+5,
  251. v1 = (hsv.v-20>20)?hsv.v-20:hsv.v+20,
  252. v2 = (hsv.v-30>20)?hsv.v-30:hsv.v+30,
  253. v3 = (hsv.v-30>70)?hsv.v-30:hsv.v+30;
  254. return new dxc.Palette([
  255. dojox.color.fromHsv(h1, s1, hsv.v),
  256. dojox.color.fromHsv(hsv.h, s2, v2),
  257. base,
  258. dojox.color.fromHsv(h2, s2, v1),
  259. dojox.color.fromHsv(h2, s3, v3)
  260. ]); // dojox.color.Palette
  261. },
  262. complementary: function(/* Object */args){
  263. var base = dojo.isString(args.base)?new dojox.color.Color(args.base):args.base,
  264. hsv = base.toHsv();
  265. var h1 = ((hsv.h*2)+137<360)?(hsv.h*2)+137:Math.floor(hsv.h/2)-137,
  266. s1 = Math.max(hsv.s-10, 0),
  267. s2 = rangeDiff(hsv.s, 10, 100),
  268. s3 = Math.min(100, hsv.s+20),
  269. v1 = Math.min(100, hsv.v+30),
  270. v2 = (hsv.v>20)?hsv.v-30:hsv.v+30;
  271. return new dxc.Palette([
  272. dojox.color.fromHsv(hsv.h, s1, v1),
  273. dojox.color.fromHsv(hsv.h, s2, v2),
  274. base,
  275. dojox.color.fromHsv(h1, s3, v2),
  276. dojox.color.fromHsv(h1, hsv.s, hsv.v)
  277. ]); // dojox.color.Palette
  278. },
  279. splitComplementary: function(/* Object */args){
  280. var base = dojo.isString(args.base)?new dojox.color.Color(args.base):args.base,
  281. dangle = args.da || 30,
  282. hsv = base.toHsv();
  283. var baseh = ((hsv.h*2)+137<360)?(hsv.h*2)+137:Math.floor(hsv.h/2)-137,
  284. h1 = (baseh-dangle+360)%360,
  285. h2 = (baseh+dangle)%360,
  286. s1 = Math.max(hsv.s-10, 0),
  287. s2 = rangeDiff(hsv.s, 10, 100),
  288. s3 = Math.min(100, hsv.s+20),
  289. v1 = Math.min(100, hsv.v+30),
  290. v2 = (hsv.v>20)?hsv.v-30:hsv.v+30;
  291. return new dxc.Palette([
  292. dojox.color.fromHsv(h1, s1, v1),
  293. dojox.color.fromHsv(h1, s2, v2),
  294. base,
  295. dojox.color.fromHsv(h2, s3, v2),
  296. dojox.color.fromHsv(h2, hsv.s, hsv.v)
  297. ]); // dojox.color.Palette
  298. },
  299. compound: function(/* Object */args){
  300. var base = dojo.isString(args.base)?new dojox.color.Color(args.base):args.base,
  301. hsv = base.toHsv();
  302. var h1 = ((hsv.h*2)+18<360)?(hsv.h*2)+18:Math.floor(hsv.h/2)-18,
  303. h2 = ((hsv.h*2)+120<360)?(hsv.h*2)+120:Math.floor(hsv.h/2)-120,
  304. h3 = ((hsv.h*2)+99<360)?(hsv.h*2)+99:Math.floor(hsv.h/2)-99,
  305. s1 = (hsv.s-40>10)?hsv.s-40:hsv.s+40,
  306. s2 = (hsv.s-10>80)?hsv.s-10:hsv.s+10,
  307. s3 = (hsv.s-25>10)?hsv.s-25:hsv.s+25,
  308. v1 = (hsv.v-40>10)?hsv.v-40:hsv.v+40,
  309. v2 = (hsv.v-20>80)?hsv.v-20:hsv.v+20,
  310. v3 = Math.max(hsv.v, 20);
  311. return new dxc.Palette([
  312. dojox.color.fromHsv(h1, s1, v1),
  313. dojox.color.fromHsv(h1, s2, v2),
  314. base,
  315. dojox.color.fromHsv(h2, s3, v3),
  316. dojox.color.fromHsv(h3, s2, v2)
  317. ]); // dojox.color.Palette
  318. },
  319. shades: function(/* Object */args){
  320. var base = dojo.isString(args.base)?new dojox.color.Color(args.base):args.base,
  321. hsv = base.toHsv();
  322. var s = (hsv.s==100 && hsv.v==0)?0:hsv.s,
  323. v1 = (hsv.v-50>20)?hsv.v-50:hsv.v+30,
  324. v2 = (hsv.v-25>=20)?hsv.v-25:hsv.v+55,
  325. v3 = (hsv.v-75>=20)?hsv.v-75:hsv.v+5,
  326. v4 = Math.max(hsv.v-10, 20);
  327. return new dxc.Palette([
  328. new dojox.color.fromHsv(hsv.h, s, v1),
  329. new dojox.color.fromHsv(hsv.h, s, v2),
  330. base,
  331. new dojox.color.fromHsv(hsv.h, s, v3),
  332. new dojox.color.fromHsv(hsv.h, s, v4)
  333. ]); // dojox.color.Palette
  334. }
  335. },
  336. generate: function(/* String|dojox.color.Color */base, /* Function|String */type){
  337. // summary
  338. // Generate a new Palette using any of the named functions in
  339. // dojox.color.Palette.generators or an optional function definition.
  340. if(dojo.isFunction(type)){
  341. return type({ base: base }); // dojox.color.Palette
  342. }
  343. else if(dxc.Palette.generators[type]){
  344. return dxc.Palette.generators[type]({ base: base }); // dojox.color.Palette
  345. }
  346. throw new Error("dojox.color.Palette.generate: the specified generator ('" + type + "') does not exist.");
  347. }
  348. });
  349. })();
  350. }