chromatography.js (34265B)
1 (function () { 2 3 var Categories, Color, ColorScale, chromato, CSSColors, Ramp, root, type, _ref, _ref2, _ref3; 4 var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; }; 5 6 root = typeof exports !== 'undefined' && exports !== null ? exports : this; 7 8 chromato = (_ref = root.chromato) != null ? _ref : root.chromato = {}; 9 10 if (typeof module !== 'undefined' && module !== null) module.exports = chromato; 11 12 Color = (function() { 13 function Color(x, y, z, m) { 14 var me, _ref2; 15 me = this; 16 if (!(x != null) && !(y != null) && !(z != null) && !(m != null)) { 17 x = [255, 0, 255]; 18 } 19 if (type(x) === 'array' && x.length === 3) { 20 if (m == null) m = y; 21 _ref2 = x, x = _ref2[0], y = _ref2[1], z = _ref2[2]; 22 } 23 if (type(x) === 'string') { 24 m = 'hex'; 25 } else { 26 if (m == null) m = 'rgb'; 27 } 28 if (m === 'rgb') { 29 me.rgb = [x, y, z]; 30 } else if (m === 'hsl') { 31 me.rgb = Color.hsl2rgb(x, y, z); 32 } else if (m === 'hsv') { 33 me.rgb = Color.hsv2rgb(x, y, z); 34 } else if (m === 'hex') { 35 me.rgb = Color.hex2rgb(x); 36 } else if (m === 'lab') { 37 me.rgb = Color.lab2rgb(x, y, z); 38 } else if (m === 'hcl') { 39 me.rgb = Color.hcl2rgb(x, y, z); 40 } else if (m === 'hsi') { 41 me.rgb = Color.hsi2rgb(x, y, z); 42 } 43 } 44 45 Color.prototype.hex = function() { 46 return Color.rgb2hex(this.rgb); 47 }; 48 49 Color.prototype.toString = function() { 50 return this.hex(); 51 }; 52 53 Color.prototype.hsl = function() { 54 return Color.rgb2hsl(this.rgb); 55 }; 56 57 Color.prototype.hsv = function() { 58 return Color.rgb2hsv(this.rgb); 59 }; 60 61 Color.prototype.lab = function() { 62 return Color.rgb2lab(this.rgb); 63 }; 64 65 Color.prototype.hcl = function() { 66 return Color.rgb2hcl(this.rgb); 67 }; 68 69 Color.prototype.hsi = function() { 70 return Color.rgb2hsi(this.rgb); 71 }; 72 73 Color.prototype.interpolate = function(f, col, m) { 74 var dh, hue, hue0, hue1, lbv, lbv0, lbv1, me, sat, sat0, sat1, xyz0, xyz1; 75 me = this; 76 if (m == null) m = 'rgb'; 77 if (type(col) === 'string') col = new Color(col); 78 if (m === 'hsl' || m === 'hsv' || m === 'hcl' || m === 'hsi') { 79 if (m === 'hsl') { 80 xyz0 = me.hsl(); 81 xyz1 = col.hsl(); 82 } else if (m === 'hsv') { 83 xyz0 = me.hsv(); 84 xyz1 = col.hsv(); 85 } else if (m === 'hcl') { 86 xyz0 = me.hcl(); 87 xyz1 = col.hcl(); 88 } else if (m === 'hsi') { 89 xyz0 = me.hsi(); 90 xyz1 = col.hsi(); 91 } 92 hue0 = xyz0[0], sat0 = xyz0[1], lbv0 = xyz0[2]; 93 hue1 = xyz1[0], sat1 = xyz1[1], lbv1 = xyz1[2]; 94 if (!isNaN(hue0) && !isNaN(hue1)) { 95 if (hue1 > hue0 && hue1 - hue0 > 180) { 96 dh = hue1 - (hue0 + 360); 97 } else if (hue1 < hue0 && hue0 - hue1 > 180) { 98 dh = hue1 + 360 - hue0; 99 } else { 100 dh = hue1 - hue0; 101 } 102 hue = hue0 + f * dh; 103 } else if (!isNaN(hue0)) { 104 hue = hue0; 105 if (lbv1 === 1 || lbv1 === 0) sat = sat0; 106 } else if (!isNaN(hue1)) { 107 hue = hue1; 108 if (lbv0 === 1 || lbv0 === 0) sat = sat1; 109 } else { 110 hue = void 0; 111 } 112 if (sat == null) sat = sat0 + f * (sat1 - sat0); 113 lbv = lbv0 + f * (lbv1 - lbv0); 114 return new Color(hue, sat, lbv, m); 115 } else if (m === 'rgb') { 116 xyz0 = me.rgb; 117 xyz1 = col.rgb; 118 return new Color(xyz0[0] + f * (xyz1[0] - xyz0[0]), xyz0[1] + f * (xyz1[1] - xyz0[1]), xyz0[2] + f * (xyz1[2] - xyz0[2]), m); 119 } else if (m === 'lab') { 120 xyz0 = me.lab(); 121 xyz1 = col.lab(); 122 return new Color(xyz0[0] + f * (xyz1[0] - xyz0[0]), xyz0[1] + f * (xyz1[1] - xyz0[1]), xyz0[2] + f * (xyz1[2] - xyz0[2]), m); 123 } else { 124 throw m + ' is not supported as a color mode'; 125 } 126 }; 127 return Color; 128 })(); 129 130 Color.hex2rgb = function(hex) { 131 var b, g, r, u; 132 if (!hex.match(/^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/)) { 133 if ((chromato.colors != null) && chromato.colors[hex]) { 134 hex = chromato.colors[hex]; 135 } else { 136 throw 'This color format is unknown: ' + hex; 137 } 138 } 139 if (hex.length === 4 || hex.length === 7) hex = hex.substr(1); 140 if (hex.length === 3) { 141 hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; 142 } 143 u = parseInt(hex, 16); 144 r = u >> 16; 145 g = u >> 8 & 0xFF; 146 b = u & 0xFF; 147 return [r, g, b]; 148 }; 149 150 Color.rgb2hex = function(r, g, b) { 151 var str, u, _ref2; 152 if (r !== void 0 && r.length === 3) { 153 _ref2 = r, r = _ref2[0], g = _ref2[1], b = _ref2[2]; 154 } 155 u = r << 16 | g << 8 | b; 156 str = '000000' + u.toString(16).toUpperCase(); 157 return '#' + str.substr(str.length - 6); 158 }; 159 160 Color.hsv2rgb = function(h, s, v) { 161 var b, f, g, i, l, p, q, r, t, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8; 162 if (type(h) === 'array' && h.length === 3) { 163 _ref2 = h, h = _ref2[0], s = _ref2[1], l = _ref2[2]; 164 } 165 v *= 255; 166 if (s === 0 && isNaN(h)) { 167 r = g = b = v; 168 } else { 169 if (h === 360) h = 0; 170 if (h > 360) h -= 360; 171 if (h < 0) h += 360; 172 h /= 60; 173 i = Math.floor(h); 174 f = h - i; 175 p = v * (1 - s); 176 q = v * (1 - s * f); 177 t = v * (1 - s * (1 - f)); 178 switch (i) { 179 case 0: 180 _ref3 = [v, t, p], r = _ref3[0], g = _ref3[1], b = _ref3[2]; 181 break; 182 case 1: 183 _ref4 = [q, v, p], r = _ref4[0], g = _ref4[1], b = _ref4[2]; 184 break; 185 case 2: 186 _ref5 = [p, v, t], r = _ref5[0], g = _ref5[1], b = _ref5[2]; 187 break; 188 case 3: 189 _ref6 = [p, q, v], r = _ref6[0], g = _ref6[1], b = _ref6[2]; 190 break; 191 case 4: 192 _ref7 = [t, p, v], r = _ref7[0], g = _ref7[1], b = _ref7[2]; 193 break; 194 case 5: 195 _ref8 = [v, p, q], r = _ref8[0], g = _ref8[1], b = _ref8[2]; 196 } 197 } 198 r = Math.round(r); 199 g = Math.round(g); 200 b = Math.round(b); 201 return [r, g, b]; 202 }; 203 204 Color.rgb2hsv = function(r, g, b) { 205 var delta, h, max, min, s, v, _ref2; 206 if (r !== void 0 && r.length === 3) { 207 _ref2 = r, r = _ref2[0], g = _ref2[1], b = _ref2[2]; 208 } 209 min = Math.min(r, g, b); 210 max = Math.max(r, g, b); 211 delta = max - min; 212 v = max / 255.0; 213 s = delta / max; 214 if (s === 0) { 215 h = void 0; 216 s = 0; 217 } else { 218 if (r === max) h = (g - b) / delta; 219 if (g === max) h = 2 + (b - r) / delta; 220 if (b === max) h = 4 + (r - g) / delta; 221 h *= 60; 222 if (h < 0) h += 360; 223 } 224 return [h, s, v]; 225 }; 226 227 Color.hsl2rgb = function(h, s, l) { 228 var b, c, g, i, r, t1, t2, t3, _ref2, _ref3; 229 if (h !== void 0 && h.length === 3) { 230 _ref2 = h, h = _ref2[0], s = _ref2[1], l = _ref2[2]; 231 } 232 if (s === 0) { 233 r = g = b = l * 255; 234 } else { 235 t3 = [0, 0, 0]; 236 c = [0, 0, 0]; 237 t2 = l < 0.5 ? l * (1 + s) : l + s - l * s; 238 t1 = 2 * l - t2; 239 h /= 360; 240 t3[0] = h + 1 / 3; 241 t3[1] = h; 242 t3[2] = h - 1 / 3; 243 for (i = 0; i <= 2; i++) { 244 if (t3[i] < 0) t3[i] += 1; 245 if (t3[i] > 1) t3[i] -= 1; 246 if (6 * t3[i] < 1) { 247 c[i] = t1 + (t2 - t1) * 6 * t3[i]; 248 } else if (2 * t3[i] < 1) { 249 c[i] = t2; 250 } else if (3 * t3[i] < 2) { 251 c[i] = t1 + (t2 - t1) * ((2 / 3) - t3[i]) * 6; 252 } else { 253 c[i] = t1; 254 } 255 } 256 _ref3 = [Math.round(c[0] * 255), Math.round(c[1] * 255), Math.round(c[2] * 255)], r = _ref3[0], g = _ref3[1], b = _ref3[2]; 257 } 258 return [r, g, b]; 259 }; 260 261 Color.rgb2hsl = function(r, g, b) { 262 var h, l, max, min, s, _ref2; 263 if (r !== void 0 && r.length === 3) { 264 _ref2 = r, r = _ref2[0], g = _ref2[1], b = _ref2[2]; 265 } 266 r /= 255; 267 g /= 255; 268 b /= 255; 269 min = Math.min(r, g, b); 270 max = Math.max(r, g, b); 271 l = (max + min) / 2; 272 if (max === min) { 273 s = 0; 274 h = void 0; 275 } else { 276 s = l < 0.5 ? (max - min) / (max + min) : (max - min) / (2 - max - min); 277 } 278 if (r === max) { 279 h = (g - b) / (max - min); 280 } else if (g === max) { 281 h = 2 + (b - r) / (max - min); 282 } else if (b === max) { 283 h = 4 + (r - g) / (max - min); 284 } 285 h *= 60; 286 if (h < 0) h += 360; 287 return [h, s, l]; 288 }; 289 290 Color.lab2xyz = function(l, a, b) { 291 var finv, ill, sl, x, y, z, _ref2; 292 if (type(l) === 'array' && l.length === 3) { 293 _ref2 = l, l = _ref2[0], a = _ref2[1], b = _ref2[2]; 294 } 295 finv = function(t) { 296 if (t > (6.0 / 29.0)) { 297 return t * t * t; 298 } else { 299 return 3 * (6.0 / 29.0) * (6.0 / 29.0) * (t - 4.0 / 29.0); 300 } 301 }; 302 sl = (l + 0.16) / 1.16; 303 ill = [0.96421, 1.00000, 0.82519]; 304 y = ill[1] * finv(sl); 305 x = ill[0] * finv(sl + (a / 5.0)); 306 z = ill[2] * finv(sl - (b / 2.0)); 307 return [x, y, z]; 308 }; 309 310 Color.xyz2rgb = function(x, y, z) { 311 var b, bl, clip, correct, g, gl, r, rl, _ref2, _ref3; 312 if (type(x) === 'array' && x.length === 3) { 313 _ref2 = x, x = _ref2[0], y = _ref2[1], z = _ref2[2]; 314 } 315 rl = 3.2406 * x - 1.5372 * y - 0.4986 * z; 316 gl = -0.9689 * x + 1.8758 * y + 0.0415 * z; 317 bl = 0.0557 * x - 0.2040 * y + 1.0570 * z; 318 clip = Math.min(rl, gl, bl) < -0.001 || Math.max(rl, gl, bl) > 1.001; 319 if (clip) { 320 rl = rl < 0.0 ? 0.0 : rl > 1.0 ? 1.0 : rl; 321 gl = gl < 0.0 ? 0.0 : gl > 1.0 ? 1.0 : gl; 322 bl = bl < 0.0 ? 0.0 : bl > 1.0 ? 1.0 : bl; 323 } 324 if (clip) { 325 _ref3 = [void 0, void 0, void 0], rl = _ref3[0], gl = _ref3[1], bl = _ref3[2]; 326 } 327 correct = function(cl) { 328 var a; 329 a = 0.055; 330 if (cl <= 0.0031308) { 331 return 12.92 * cl; 332 } else { 333 return (1 + a) * Math.pow(cl, 1 / 2.4) - a; 334 } 335 }; 336 r = Math.round(255.0 * correct(rl)); 337 g = Math.round(255.0 * correct(gl)); 338 b = Math.round(255.0 * correct(bl)); 339 return [r, g, b]; 340 }; 341 342 Color.lab2rgb = function(l, a, b) { 343 var x, y, z, _ref2, _ref3, _ref4; 344 if (l !== void 0 && l.length === 3) { 345 _ref2 = l, l = _ref2[0], a = _ref2[1], b = _ref2[2]; 346 } 347 if (l !== void 0 && l.length === 3) { 348 _ref3 = l, l = _ref3[0], a = _ref3[1], b = _ref3[2]; 349 } 350 _ref4 = Color.lab2xyz(l, a, b), x = _ref4[0], y = _ref4[1], z = _ref4[2]; 351 return Color.xyz2rgb(x, y, z); 352 }; 353 354 Color.hcl2lab = function(c, s, l) { 355 var L, tau_const, a, angle, b, r, _ref2; 356 if (type(c) === 'array' && c.length === 3) { 357 _ref2 = c, c = _ref2[0], s = _ref2[1], l = _ref2[2]; 358 } 359 c /= 360.0; 360 tau_const = 6.283185307179586476925287; 361 L = l * 0.61 + 0.09; 362 angle = tau_const / 6.0 - c * tau_const; 363 r = (l * 0.311 + 0.125) * s; 364 a = Math.sin(angle) * r; 365 b = Math.cos(angle) * r; 366 return [L, a, b]; 367 }; 368 369 Color.hcl2rgb = function(c, s, l) { 370 var L, a, b, _ref2; 371 _ref2 = Color.hcl2lab(c, s, l), L = _ref2[0], a = _ref2[1], b = _ref2[2]; 372 return Color.lab2rgb(L, a, b); 373 }; 374 375 Color.rgb2xyz = function(r, g, b) { 376 var bl, correct, gl, rl, x, y, z, _ref2; 377 if (r !== void 0 && r.length === 3) { 378 _ref2 = r, r = _ref2[0], g = _ref2[1], b = _ref2[2]; 379 } 380 correct = function(c) { 381 var a; 382 a = 0.055; 383 if (c <= 0.04045) { 384 return c / 12.92; 385 } else { 386 return Math.pow((c + a) / (1 + a), 2.4); 387 } 388 }; 389 rl = correct(r / 255.0); 390 gl = correct(g / 255.0); 391 bl = correct(b / 255.0); 392 x = 0.4124 * rl + 0.3576 * gl + 0.1805 * bl; 393 y = 0.2126 * rl + 0.7152 * gl + 0.0722 * bl; 394 z = 0.0193 * rl + 0.1192 * gl + 0.9505 * bl; 395 return [x, y, z]; 396 }; 397 398 Color.xyz2lab = function(x, y, z) { 399 var a, b, f, ill, l, _ref2; 400 if (x !== void 0 && x.length === 3) { 401 _ref2 = x, x = _ref2[0], y = _ref2[1], z = _ref2[2]; 402 } 403 ill = [0.96421, 1.00000, 0.82519]; 404 f = function(t) { 405 if (t > Math.pow(6.0 / 29.0, 3)) { 406 return Math.pow(t, 1 / 3); 407 } else { 408 return (1 / 3) * (29 / 6) * (29 / 6) * t + 4.0 / 29.0; 409 } 410 }; 411 l = 1.16 * f(y / ill[1]) - 0.16; 412 a = 5 * (f(x / ill[0]) - f(y / ill[1])); 413 b = 2 * (f(y / ill[1]) - f(z / ill[2])); 414 return [l, a, b]; 415 }; 416 417 Color.rgb2lab = function(r, g, b) { 418 var x, y, z, _ref2, _ref3; 419 if (r !== void 0 && r.length === 3) { 420 _ref2 = r, r = _ref2[0], g = _ref2[1], b = _ref2[2]; 421 } 422 _ref3 = Color.rgb2xyz(r, g, b), x = _ref3[0], y = _ref3[1], z = _ref3[2]; 423 return Color.xyz2lab(x, y, z); 424 }; 425 426 Color.lab2hcl = function(l, a, b) { 427 var L, tau_const, angle, c, r, s, _ref2; 428 if (type(l) === 'array' && l.length === 3) { 429 _ref2 = l, l = _ref2[0], a = _ref2[1], b = _ref2[2]; 430 } 431 L = l; 432 l = (l - 0.09) / 0.61; 433 r = Math.sqrt(a * a + b * b); 434 s = r / (l * 0.311 + 0.125); 435 tau_const = 6.283185307179586476925287; 436 angle = Math.atan2(a, b); 437 c = (tau_const / 6 - angle) / tau_const; 438 c *= 360; 439 if (c < 0) c += 360; 440 return [c, s, l]; 441 }; 442 443 Color.rgb2hcl = function(r, g, b) { 444 var a, l, _ref2, _ref3; 445 if (type(r) === 'array' && r.length === 3) { 446 _ref2 = r, r = _ref2[0], g = _ref2[1], b = _ref2[2]; 447 } 448 _ref3 = Color.rgb2lab(r, g, b), l = _ref3[0], a = _ref3[1], b = _ref3[2]; 449 return Color.lab2hcl(l, a, b); 450 }; 451 452 Color.rgb2hsi = function(r, g, b) { 453 var pi_const_x2, h, i, min, s, _ref2; 454 if (type(r) === 'array' && r.length === 3) { 455 _ref2 = r, r = _ref2[0], g = _ref2[1], b = _ref2[2]; 456 } 457 pi_const_x2 = Math.PI * 2; 458 r /= 255; 459 g /= 255; 460 b /= 255; 461 min = Math.min(r, g, b); 462 i = (r + g + b) / 3; 463 s = 1 - min / i; 464 if (s === 0) { 465 h = 0; 466 } else { 467 h = ((r - g) + (r - b)) / 2; 468 h /= Math.sqrt((r - g) * (r - g) + (r - b) * (g - b)); 469 h = Math.acos(h); 470 if (b > g) h = pi_const_x2 - h; 471 h /= pi_const_x2; 472 } 473 return [h * 360, s, i]; 474 }; 475 476 Color.hsi2rgb = function(h, s, i) { 477 var pi_const_div3, pi_const_x2, b, cos, g, r, _ref2; 478 if (type(h) === 'array' && h.length === 3) { 479 _ref2 = h, h = _ref2[0], s = _ref2[1], i = _ref2[2]; 480 } 481 pi_const_x2 = Math.PI * 2; 482 pi_const_div3 = Math.PI / 3; 483 cos = Math.cos; 484 if (h < 0) h += 360; 485 if (h > 360) h -= 360; 486 h /= 360; 487 if (h < 1 / 3) { 488 b = (1 - s) / 3; 489 r = (1 + s * cos(pi_const_x2 * h) / cos(pi_const_div3 - pi_const_x2 * h)) / 3; 490 g = 1 - (b + r); 491 } else if (h < 2 / 3) { 492 h -= 1 / 3; 493 r = (1 - s) / 3; 494 g = (1 + s * cos(pi_const_x2 * h) / cos(pi_const_div3 - pi_const_x2 * h)) / 3; 495 b = 1 - (r + g); 496 } else { 497 h -= 2 / 3; 498 g = (1 - s) / 3; 499 b = (1 + s * cos(pi_const_x2 * h) / cos(pi_const_div3 - pi_const_x2 * h)) / 3; 500 r = 1 - (g + b); 501 } 502 r = i * r * 3; 503 g = i * g * 3; 504 b = i * b * 3; 505 return [r * 255, g * 255, b * 255]; 506 }; 507 508 chromato.Color = Color; 509 510 chromato.hsl = function(h, s, l) { 511 return new Color(h, s, l, 'hsl'); 512 }; 513 514 chromato.hsv = function(h, s, v) { 515 return new Color(h, s, v, 'hsv'); 516 }; 517 518 chromato.rgb = function(r, g, b) { 519 return new Color(r, g, b, 'rgb'); 520 }; 521 522 chromato.hex = function(x) { 523 return new Color(x); 524 }; 525 526 chromato.lab = function(l, a, b) { 527 return new Color(l, a, b, 'lab'); 528 }; 529 530 chromato.hcl = function(c, s, l) { 531 return new Color(c, s, l, 'hcl'); 532 }; 533 534 chromato.hsi = function(h, s, i) { 535 return new Color(h, s, i, 'hsi'); 536 }; 537 538 chromato.interpolate = function(a, b, f, m) { 539 if (type(a) === 'string') a = new Color(a); 540 if (type(b) === 'string') b = new Color(b); 541 return a.interpolate(f, b, m); 542 }; 543 544 ColorScale = (function() { 545 546 function ColorScale(opts) { 547 var c, col, cols, me, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7; 548 me = this; 549 me.colors = cols = (_ref2 = opts.colors) != null ? _ref2 : ['#ddd', '#222']; 550 for (c = 0, _ref3 = cols.length - 1; 0 <= _ref3 ? c <= _ref3 : c >= _ref3; 0 <= _ref3 ? c++ : c--) { 551 col = cols[c]; 552 if (type(col) === 'string') cols[c] = new Color(col); 553 } 554 if (opts.positions != null) { 555 me.pos = opts.positions; 556 } else { 557 me.pos = []; 558 for (c = 0, _ref4 = cols.length - 1; 0 <= _ref4 ? c <= _ref4 : c >= _ref4; 0 <= _ref4 ? c++ : c--) { 559 me.pos.push(c / (cols.length - 1)); 560 } 561 } 562 me.mode = (_ref5 = opts.mode) != null ? _ref5 : 'hsv'; 563 me.nacol = (_ref6 = opts.nacol) != null ? _ref6 : '#ccc'; 564 me.setClasses((_ref7 = opts.limits) != null ? _ref7 : [0, 1]); 565 me; 566 } 567 568 ColorScale.prototype.getColor = function(value) { 569 var c, f, f0, me; 570 me = this; 571 if (isNaN(value)) return me.nacol; 572 if (me.classLimits.length > 2) { 573 c = me.getClass(value); 574 f = c / (me.numClasses - 1); 575 } else { 576 f = f0 = (value - me.min) / (me.max - me.min); 577 f = Math.min(1, Math.max(0, f)); 578 } 579 return me.fColor(f); 580 }; 581 582 ColorScale.prototype.fColor = function(f) { 583 var col, cols, i, me, p, _ref2; 584 me = this; 585 cols = me.colors; 586 for (i = 0, _ref2 = me.pos.length - 1; 0 <= _ref2 ? i <= _ref2 : i >= _ref2; 0 <= _ref2 ? i++ : i--) { 587 p = me.pos[i]; 588 if (f <= p) { 589 col = cols[i]; 590 break; 591 } 592 if (f >= p && i === me.pos.length - 1) { 593 col = cols[i]; 594 break; 595 } 596 if (f > p && f < me.pos[i + 1]) { 597 f = (f - p) / (me.pos[i + 1] - p); 598 col = chromato.interpolate(cols[i], cols[i + 1], f, me.mode); 599 break; 600 } 601 } 602 return col; 603 }; 604 605 ColorScale.prototype.classifyValue = function(value) { 606 var i, limits, maxc, minc, n, self; 607 self = this; 608 limits = self.classLimits; 609 if (limits.length > 2) { 610 n = limits.length - 1; 611 i = self.getClass(value); 612 value = limits[i] + (limits[i + 1] - limits[i]) * 0.5; 613 minc = limits[0]; 614 maxc = limits[n - 1]; 615 value = self.min + ((value - minc) / (maxc - minc)) * (self.max - self.min); 616 } 617 return value; 618 }; 619 620 ColorScale.prototype.setClasses = function(limits) { 621 var me; 622 if (limits == null) limits = []; 623 me = this; 624 me.classLimits = limits; 625 me.min = limits[0]; 626 me.max = limits[limits.length - 1]; 627 if (limits.length === 2) { 628 return me.numClasses = 0; 629 } else { 630 return me.numClasses = limits.length - 1; 631 } 632 }; 633 634 ColorScale.prototype.getClass = function(value) { 635 var i, limits, n, self; 636 self = this; 637 limits = self.classLimits; 638 if (limits != null) { 639 n = limits.length - 1; 640 i = 0; 641 while (i < n && value >= limits[i]) { 642 i++; 643 } 644 return i - 1; 645 } 646 }; 647 648 ColorScale.prototype.validValue = function(value) { 649 return !isNaN(value); 650 }; 651 return ColorScale; 652 })(); 653 654 chromato.ColorScale = ColorScale; 655 656 Ramp = (function() { 657 __extends(Ramp, ColorScale); 658 659 function Ramp(col0, col1, mode) { 660 if (col0 == null) col0 = '#fe0000'; 661 if (col1 == null) col1 = '#feeeee'; 662 if (mode == null) mode = 'hsl'; 663 Ramp.__super__.constructor.call(this, [col0, col1], [0, 1], mode); 664 } 665 return Ramp; 666 })(); 667 668 chromato.Ramp = Ramp; 669 670 Categories = (function() { 671 __extends(Categories, ColorScale); 672 673 function Categories(colors) { 674 var me; 675 me = this; 676 me.colors = colors; 677 } 678 679 Categories.prototype.parseData = function(data, data_col) {}; 680 681 Categories.prototype.getColor = function(value) { 682 var me; 683 me = this; 684 if (me.colors.hasOwnProperty(value)) { 685 return me.colors[value]; 686 } else { 687 return '#cccccc'; 688 } 689 }; 690 691 Categories.prototype.validValue = function(value) { 692 return this.colors.hasOwnProperty(value); 693 }; 694 return Categories; 695 })(); 696 697 chromato.Categories = Categories; 698 699 CSSColors = (function() { 700 __extends(CSSColors, ColorScale); 701 702 function CSSColors(name) { 703 var me; 704 me = this; 705 me.name = name; 706 me.setClasses(7); 707 me; 708 } 709 710 CSSColors.prototype.getColor = function(value) { 711 var c, me; 712 me = this; 713 c = me.getClass(value); 714 return me.name + ' l' + me.numClasses + ' c' + c; 715 }; 716 717 return CSSColors; 718 })(); 719 720 chromato.CSSColors = CSSColors; 721 722 if ((_ref2 = chromato.scales) == null) chromato.scales = {}; 723 724 chromato.limits = function(data, mode, num, prop) { 725 var assignments, best, centroids, cluster, clusterSizes, dist, i, j, k, kClusters, limits, max, min, mindist, n, nb_iters, newCentroids, p, pb, pr, repeat, row, sum, tmpKMeansBreaks, val, value, values, _i, _j, _k, _len, _len2, _len3, _ref10, _ref11, _ref12, _ref13, _ref14, _ref15, _ref16, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8, _ref9; 726 if (mode == null) mode = 'equal'; 727 if (num == null) num = 7; 728 if (prop == null) prop = null; 729 min = Number.MAX_VALUE; 730 max = Number.MAX_VALUE * -1; 731 sum = 0; 732 values = []; 733 if (type(data) === 'array') { 734 if (type(data[0]) !== 'object' && type(data[0]) !== 'array') { 735 for (_i = 0, _len = data.length; _i < _len; _i++) { 736 val = data[_i]; 737 if (!isNaN(val)) values.push(Number(val)); 738 } 739 } else { 740 for (_j = 0, _len2 = data.length; _j < _len2; _j++) { 741 row = data[_j]; 742 values.push(Number(row[prop])); 743 } 744 } 745 } else if (type(data) === 'object') { 746 for (k in data) { 747 val = data[k]; 748 if (type(val) === 'object' && type(prop) === 'string') { 749 if (!isNaN(val[prop])) values.push(Number(val[prop])); 750 } else if (type(val) === 'array' && type(prop) === 'number') { 751 if (!isNaN(val[prop])) values.push(Number(val[prop])); 752 } else if (type(val) === 'number') { 753 if (!isNaN(val)) values.push(Number(val)); 754 } 755 } 756 } 757 for (_k = 0, _len3 = values.length; _k < _len3; _k++) { 758 val = values[_k]; 759 if (!!isNaN(val)) continue; 760 if (val < min) min = val; 761 if (val > max) max = val; 762 sum += val; 763 } 764 values = values.sort(function(a, b) { 765 return a - b; 766 }); 767 limits = []; 768 if (mode.substr(0, 1) === 'c') { 769 limits.push(min); 770 limits.push(max); 771 } 772 if (mode.substr(0, 1) === 'e') { 773 limits.push(min); 774 for (i = 1, _ref3 = num - 1; 1 <= _ref3 ? i <= _ref3 : i >= _ref3; 1 <= _ref3 ? i++ : i--) { 775 limits.push(min + (i / num) * (max - min)); 776 } 777 limits.push(max); 778 } else if (mode.substr(0, 1) === 'q') { 779 limits.push(min); 780 for (i = 1, _ref4 = num - 1; 1 <= _ref4 ? i <= _ref4 : i >= _ref4; 1 <= _ref4 ? i++ : i--) { 781 p = values.length * i / num; 782 pb = Math.floor(p); 783 if (pb === p) { 784 limits.push(values[pb]); 785 } else { 786 pr = p - pb; 787 limits.push(values[pb] * pr + values[pb + 1] * (1 - pr)); 788 } 789 } 790 limits.push(max); 791 } else if (mode.substr(0, 1) === 'k') { 792 n = values.length; 793 assignments = new Array(n); 794 clusterSizes = new Array(num); 795 repeat = true; 796 nb_iters = 0; 797 centroids = null; 798 centroids = []; 799 centroids.push(min); 800 for (i = 1, _ref5 = num - 1; 1 <= _ref5 ? i <= _ref5 : i >= _ref5; 1 <= _ref5 ? i++ : i--) { 801 centroids.push(min + (i / num) * (max - min)); 802 } 803 centroids.push(max); 804 while (repeat) { 805 for (j = 0, _ref6 = num - 1; 0 <= _ref6 ? j <= _ref6 : j >= _ref6; 0 <= _ref6 ? j++ : j--) { 806 clusterSizes[j] = 0; 807 } 808 for (i = 0, _ref7 = n - 1; 0 <= _ref7 ? i <= _ref7 : i >= _ref7; 0 <= _ref7 ? i++ : i--) { 809 value = values[i]; 810 mindist = Number.MAX_VALUE; 811 for (j = 0, _ref8 = num - 1; 0 <= _ref8 ? j <= _ref8 : j >= _ref8; 0 <= _ref8 ? j++ : j--) { 812 dist = Math.abs(centroids[j] - value); 813 if (dist < mindist) { 814 mindist = dist; 815 best = j; 816 } 817 } 818 clusterSizes[best]++; 819 assignments[i] = best; 820 } 821 newCentroids = new Array(num); 822 for (j = 0, _ref9 = num - 1; 0 <= _ref9 ? j <= _ref9 : j >= _ref9; 0 <= _ref9 ? j++ : j--) { 823 newCentroids[j] = null; 824 } 825 for (i = 0, _ref10 = n - 1; 0 <= _ref10 ? i <= _ref10 : i >= _ref10; 0 <= _ref10 ? i++ : i--) { 826 cluster = assignments[i]; 827 if (newCentroids[cluster] === null) { 828 newCentroids[cluster] = values[i]; 829 } else { 830 newCentroids[cluster] += values[i]; 831 } 832 } 833 for (j = 0, _ref11 = num - 1; 0 <= _ref11 ? j <= _ref11 : j >= _ref11; 0 <= _ref11 ? j++ : j--) { 834 newCentroids[j] *= 1 / clusterSizes[j]; 835 } 836 repeat = false; 837 for (j = 0, _ref12 = num - 1; 0 <= _ref12 ? j <= _ref12 : j >= _ref12; 0 <= _ref12 ? j++ : j--) { 838 if (newCentroids[j] !== centroids[i]) { 839 repeat = true; 840 break; 841 } 842 } 843 centroids = newCentroids; 844 nb_iters++; 845 if (nb_iters > 200) repeat = false; 846 } 847 kClusters = {}; 848 for (j = 0, _ref13 = num - 1; 0 <= _ref13 ? j <= _ref13 : j >= _ref13; 0 <= _ref13 ? j++ : j--) { 849 kClusters[j] = []; 850 } 851 for (i = 0, _ref14 = n - 1; 0 <= _ref14 ? i <= _ref14 : i >= _ref14; 0 <= _ref14 ? i++ : i--) { 852 cluster = assignments[i]; 853 kClusters[cluster].push(values[i]); 854 } 855 tmpKMeansBreaks = []; 856 for (j = 0, _ref15 = num - 1; 0 <= _ref15 ? j <= _ref15 : j >= _ref15; 0 <= _ref15 ? j++ : j--) { 857 tmpKMeansBreaks.push(kClusters[j][0]); 858 tmpKMeansBreaks.push(kClusters[j][kClusters[j].length - 1]); 859 } 860 tmpKMeansBreaks = tmpKMeansBreaks.sort(function(a, b) { 861 return a - b; 862 }); 863 limits.push(tmpKMeansBreaks[0]); 864 for (i = 1, _ref16 = tmpKMeansBreaks.length - 1; i <= _ref16; i += 2) { 865 if (!isNaN(tmpKMeansBreaks[i])) limits.push(tmpKMeansBreaks[i]); 866 } 867 } 868 return limits; 869 }; 870 871 root = typeof exports !== 'undefined' && exports !== null ? exports : this; 872 873 type = (function() { 874 var classToType, name, _i, _len, _ref3; 875 classToType = {}; 876 _ref3 = 'Boolean Number String Function Array Date RegExp Undefined Null'.split(' '); 877 for (_i = 0, _len = _ref3.length; _i < _len; _i++) { 878 name = _ref3[_i]; 879 classToType['[object ' + name + ']'] = name.toLowerCase(); 880 } 881 return function(obj) { 882 var strType; 883 strType = Object.prototype.toString.call(obj); 884 return classToType[strType] || 'object'; 885 }; 886 })(); 887 888 if ((_ref3 = root.type) == null) root.type = type; 889 890 Array.max = function(array) { 891 return Math.max.apply(Math, array); 892 }; 893 894 Array.min = function(array) { 895 return Math.min.apply(Math, array); 896 }; 897 898 }).call(this); 899 900 var createPalette = { 901 generate: function(colorsCount, checkColor, forceMode, quality, ultra_precision){ 902 if(colorsCount === undefined) 903 colorsCount = 8; 904 if(checkColor === undefined) 905 checkColor = function(x){return true;}; 906 if(forceMode === undefined) 907 forceMode = false; 908 if(quality === undefined) 909 quality = 50; 910 ultra_precision = ultra_precision || false 911 912 if(forceMode){ 913 var colors = []; 914 function checkLab(lab){ 915 var color = chromato.lab(lab[0], lab[1], lab[2]); 916 return !isNaN(color.rgb[0]) && color.rgb[0] >= 0 && color.rgb[1] >= 0 && color.rgb[2] >= 0 && color.rgb[0] < 256 && color.rgb[1] < 256 && color.rgb[2] < 256 && checkColor(color); 917 } 918 919 var vectors = {}; 920 for(i = 0; i < colorsCount; i++){ 921 var color = [Math.random(), 2 * Math.random() - 1, 2 * Math.random() - 1]; 922 while(!checkLab(color)){ 923 color = [Math.random(), 2 * Math.random() - 1, 2 * Math.random() - 1]; 924 } 925 colors.push(color); 926 } 927 928 var repulsion = 0.3; 929 var speed = 0.05; 930 var steps = quality * 20; 931 while(steps-- > 0){ 932 for(i = 0; i < colors.length; i++){ 933 vectors[i] = {dl:0, da:0, db:0}; 934 } 935 for(i = 0; i < colors.length; i++){ 936 var color_a = colors[i]; 937 for(j = 0; j < i; j++){ 938 var color_b = colors[j]; 939 var dl = color_a[0] - color_b[0]; 940 var da = color_a[1] - color_b[1]; 941 var db = color_a[2] - color_b[2]; 942 var d = Math.sqrt(Math.pow(dl, 2) + Math.pow(da, 2) + Math.pow(db, 2)); 943 if(d > 0){ 944 var force = repulsion / Math.pow(d, 2); 945 vectors[i].dl += dl * force / d; 946 vectors[i].da += da * force / d; 947 vectors[i].db += db * force / d; 948 vectors[j].dl -= dl * force / d; 949 vectors[j].da -= da * force / d; 950 vectors[j].db -= db * force / d; 951 } else { 952 vectors[j].dl += 0.02 - 0.04 * Math.random(); 953 vectors[j].da += 0.02 - 0.04 * Math.random(); 954 vectors[j].db += 0.02 - 0.04 * Math.random(); 955 } 956 } 957 } 958 for(i = 0; i < colors.length; i++){ 959 var color = colors[i]; 960 var displacement = speed * Math.sqrt(Math.pow(vectors[i].dl, 2) + Math.pow(vectors[i].da, 2) + Math.pow(vectors[i].db, 2)); 961 if(displacement>0){ 962 var ratio = speed * Math.min(0.1, displacement)/displacement; 963 candidateLab = [color[0] + vectors[i].dl * ratio, color[1] + vectors[i].da * ratio, color[2] + vectors[i].db * ratio]; 964 if(checkLab(candidateLab)){ 965 colors[i] = candidateLab; 966 } 967 } 968 } 969 } 970 return colors.map(function(lab){return chromato.lab(lab[0], lab[1], lab[2]);}); 971 } else { 972 function checkColor2(color){ 973 var lab = color.lab(); 974 var hcl = color.hcl(); 975 return !isNaN(color.rgb[0]) && color.rgb[0] >= 0 && color.rgb[1] >= 0 && color.rgb[2] >= 0 && color.rgb[0]<256 && color.rgb[1]<256 && color.rgb[2]<256 && checkColor(color); 976 } 977 var kMeans = []; 978 for(i = 0; i < colorsCount; i++){ 979 var lab = [Math.random(), 2 * Math.random() - 1, 2 * Math.random() - 1]; 980 while(!checkColor2(chromato.lab(lab))){ 981 lab = [Math.random(), 2 * Math.random() - 1, 2 * Math.random() - 1]; 982 } 983 kMeans.push(lab); 984 } 985 var colorSamples = []; 986 var samplesClosest = []; 987 if(ultra_precision){ 988 for(l = 0; l <= 1; l += 0.01){ 989 for(a =- 1; a <= 1; a += 0.05){ 990 for(b =- 1; b <= 1; b += 0.05){ 991 if(checkColor2(chromato.lab(l, a, b))){ 992 colorSamples.push([l, a, b]); 993 samplesClosest.push(null); 994 } 995 } 996 } 997 } 998 } else { 999 for(l = 0; l <= 1; l += 0.05){ 1000 for(a =- 1; a <= 1; a += 0.1){ 1001 for(b =- 1; b <= 1; b += 0.1){ 1002 if(checkColor2(chromato.lab(l, a, b))){ 1003 colorSamples.push([l, a, b]); 1004 samplesClosest.push(null); 1005 } 1006 } 1007 } 1008 } 1009 } 1010 var steps = quality; 1011 while(steps-- > 0){ 1012 for(i = 0; i < colorSamples.length; i++){ 1013 var lab = colorSamples[i]; 1014 var min_dist = 1000000; 1015 for(j = 0; j < kMeans.length; j++){ 1016 var kMean = kMeans[j]; 1017 var distance = Math.sqrt(Math.pow(lab[0] - kMean[0], 2) + Math.pow(lab[1]-kMean[1], 2) + Math.pow(lab[2] - kMean[2], 2)); 1018 if(distance < min_dist){ 1019 min_dist = distance; 1020 samplesClosest[i] = j; 1021 } 1022 } 1023 } 1024 var freeColorSamples = colorSamples.slice(0); 1025 for(j = 0; j < kMeans.length; j++){ 1026 var count = 0; 1027 var candidateKMean = [0, 0, 0]; 1028 for(i = 0; i < colorSamples.length; i++){ 1029 if(samplesClosest[i] == j){ 1030 count++; 1031 candidateKMean[0] += colorSamples[i][0]; 1032 candidateKMean[1] += colorSamples[i][1]; 1033 candidateKMean[2] += colorSamples[i][2]; 1034 } 1035 } 1036 if(count != 0){ 1037 candidateKMean[0] /= count; 1038 candidateKMean[1] /= count; 1039 candidateKMean[2] /= count; 1040 } 1041 if(count != 0 && checkColor2(chromato.lab(candidateKMean[0], candidateKMean[1], candidateKMean[2])) && candidateKMean){ 1042 kMeans[j] = candidateKMean; 1043 } else { 1044 if(freeColorSamples.length>0){ 1045 var min_dist = 10000000000; 1046 var closest = -1; 1047 for(i = 0; i<freeColorSamples.length; i++){ 1048 var distance = Math.sqrt(Math.pow(freeColorSamples[i][0] - candidateKMean[0], 2) + Math.pow(freeColorSamples[i][1] - candidateKMean[1], 2) + Math.pow(freeColorSamples[i][2] - candidateKMean[2], 2)); 1049 if(distance < min_dist){ 1050 min_dist = distance; 1051 closest = i; 1052 } 1053 } 1054 kMeans[j] = colorSamples[closest]; 1055 } else { 1056 var min_dist = 10000000000; 1057 var closest = -1; 1058 for(i = 0; i < colorSamples.length; i++){ 1059 var distance = Math.sqrt(Math.pow(colorSamples[i][0] - candidateKMean[0], 2) + Math.pow(colorSamples[i][1]-candidateKMean[1], 2) + Math.pow(colorSamples[i][2] - candidateKMean[2], 2)); 1060 if(distance < min_dist){ 1061 min_dist = distance; 1062 closest = i; 1063 } 1064 } 1065 kMeans[j] = colorSamples[closest]; 1066 } 1067 } 1068 freeColorSamples = freeColorSamples.filter(function(color){ 1069 return color[0] != kMeans[j][0] 1070 || color[1] != kMeans[j][1] 1071 || color[2] != kMeans[j][2]; 1072 }); 1073 } 1074 } 1075 return kMeans.map(function(lab){return chromato.lab(lab[0], lab[1], lab[2]);}); 1076 } 1077 }, 1078 1079 diffSort: function(colorsToSort){ 1080 var diffColors = [colorsToSort.shift()]; 1081 while(colorsToSort.length > 0){ 1082 var index = -1; 1083 var maxDistance = -1; 1084 for(candidate_index = 0; candidate_index < colorsToSort.length; candidate_index++){ 1085 var d = 1000000000; 1086 for(i = 0; i < diffColors.length; i++){ 1087 var color_a = colorsToSort[candidate_index].lab(); 1088 var color_b = diffColors[i].lab(); 1089 var dl = color_a[0] - color_b[0]; 1090 var da = color_a[1] - color_b[1]; 1091 var db = color_a[2] - color_b[2]; 1092 d = Math.min(d, Math.sqrt(Math.pow(dl, 2)+Math.pow(da, 2)+Math.pow(db, 2))); 1093 } 1094 if(d > maxDistance){ 1095 maxDistance = d; 1096 index = candidate_index; 1097 } 1098 } 1099 var color = colorsToSort[index]; 1100 diffColors.push(color); 1101 colorsToSort = colorsToSort.filter(function(c,i){return i != index;}); 1102 } 1103 return diffColors; 1104 } 1105 }