UNPKG

16.1 kBJavaScriptView Raw
1import LRU from '../core/LRU.js';
2import { extend, isGradientObject, isString, map } from '../core/util.js';
3var kCSSColorTable = {
4 'transparent': [0, 0, 0, 0], 'aliceblue': [240, 248, 255, 1],
5 'antiquewhite': [250, 235, 215, 1], 'aqua': [0, 255, 255, 1],
6 'aquamarine': [127, 255, 212, 1], 'azure': [240, 255, 255, 1],
7 'beige': [245, 245, 220, 1], 'bisque': [255, 228, 196, 1],
8 'black': [0, 0, 0, 1], 'blanchedalmond': [255, 235, 205, 1],
9 'blue': [0, 0, 255, 1], 'blueviolet': [138, 43, 226, 1],
10 'brown': [165, 42, 42, 1], 'burlywood': [222, 184, 135, 1],
11 'cadetblue': [95, 158, 160, 1], 'chartreuse': [127, 255, 0, 1],
12 'chocolate': [210, 105, 30, 1], 'coral': [255, 127, 80, 1],
13 'cornflowerblue': [100, 149, 237, 1], 'cornsilk': [255, 248, 220, 1],
14 'crimson': [220, 20, 60, 1], 'cyan': [0, 255, 255, 1],
15 'darkblue': [0, 0, 139, 1], 'darkcyan': [0, 139, 139, 1],
16 'darkgoldenrod': [184, 134, 11, 1], 'darkgray': [169, 169, 169, 1],
17 'darkgreen': [0, 100, 0, 1], 'darkgrey': [169, 169, 169, 1],
18 'darkkhaki': [189, 183, 107, 1], 'darkmagenta': [139, 0, 139, 1],
19 'darkolivegreen': [85, 107, 47, 1], 'darkorange': [255, 140, 0, 1],
20 'darkorchid': [153, 50, 204, 1], 'darkred': [139, 0, 0, 1],
21 'darksalmon': [233, 150, 122, 1], 'darkseagreen': [143, 188, 143, 1],
22 'darkslateblue': [72, 61, 139, 1], 'darkslategray': [47, 79, 79, 1],
23 'darkslategrey': [47, 79, 79, 1], 'darkturquoise': [0, 206, 209, 1],
24 'darkviolet': [148, 0, 211, 1], 'deeppink': [255, 20, 147, 1],
25 'deepskyblue': [0, 191, 255, 1], 'dimgray': [105, 105, 105, 1],
26 'dimgrey': [105, 105, 105, 1], 'dodgerblue': [30, 144, 255, 1],
27 'firebrick': [178, 34, 34, 1], 'floralwhite': [255, 250, 240, 1],
28 'forestgreen': [34, 139, 34, 1], 'fuchsia': [255, 0, 255, 1],
29 'gainsboro': [220, 220, 220, 1], 'ghostwhite': [248, 248, 255, 1],
30 'gold': [255, 215, 0, 1], 'goldenrod': [218, 165, 32, 1],
31 'gray': [128, 128, 128, 1], 'green': [0, 128, 0, 1],
32 'greenyellow': [173, 255, 47, 1], 'grey': [128, 128, 128, 1],
33 'honeydew': [240, 255, 240, 1], 'hotpink': [255, 105, 180, 1],
34 'indianred': [205, 92, 92, 1], 'indigo': [75, 0, 130, 1],
35 'ivory': [255, 255, 240, 1], 'khaki': [240, 230, 140, 1],
36 'lavender': [230, 230, 250, 1], 'lavenderblush': [255, 240, 245, 1],
37 'lawngreen': [124, 252, 0, 1], 'lemonchiffon': [255, 250, 205, 1],
38 'lightblue': [173, 216, 230, 1], 'lightcoral': [240, 128, 128, 1],
39 'lightcyan': [224, 255, 255, 1], 'lightgoldenrodyellow': [250, 250, 210, 1],
40 'lightgray': [211, 211, 211, 1], 'lightgreen': [144, 238, 144, 1],
41 'lightgrey': [211, 211, 211, 1], 'lightpink': [255, 182, 193, 1],
42 'lightsalmon': [255, 160, 122, 1], 'lightseagreen': [32, 178, 170, 1],
43 'lightskyblue': [135, 206, 250, 1], 'lightslategray': [119, 136, 153, 1],
44 'lightslategrey': [119, 136, 153, 1], 'lightsteelblue': [176, 196, 222, 1],
45 'lightyellow': [255, 255, 224, 1], 'lime': [0, 255, 0, 1],
46 'limegreen': [50, 205, 50, 1], 'linen': [250, 240, 230, 1],
47 'magenta': [255, 0, 255, 1], 'maroon': [128, 0, 0, 1],
48 'mediumaquamarine': [102, 205, 170, 1], 'mediumblue': [0, 0, 205, 1],
49 'mediumorchid': [186, 85, 211, 1], 'mediumpurple': [147, 112, 219, 1],
50 'mediumseagreen': [60, 179, 113, 1], 'mediumslateblue': [123, 104, 238, 1],
51 'mediumspringgreen': [0, 250, 154, 1], 'mediumturquoise': [72, 209, 204, 1],
52 'mediumvioletred': [199, 21, 133, 1], 'midnightblue': [25, 25, 112, 1],
53 'mintcream': [245, 255, 250, 1], 'mistyrose': [255, 228, 225, 1],
54 'moccasin': [255, 228, 181, 1], 'navajowhite': [255, 222, 173, 1],
55 'navy': [0, 0, 128, 1], 'oldlace': [253, 245, 230, 1],
56 'olive': [128, 128, 0, 1], 'olivedrab': [107, 142, 35, 1],
57 'orange': [255, 165, 0, 1], 'orangered': [255, 69, 0, 1],
58 'orchid': [218, 112, 214, 1], 'palegoldenrod': [238, 232, 170, 1],
59 'palegreen': [152, 251, 152, 1], 'paleturquoise': [175, 238, 238, 1],
60 'palevioletred': [219, 112, 147, 1], 'papayawhip': [255, 239, 213, 1],
61 'peachpuff': [255, 218, 185, 1], 'peru': [205, 133, 63, 1],
62 'pink': [255, 192, 203, 1], 'plum': [221, 160, 221, 1],
63 'powderblue': [176, 224, 230, 1], 'purple': [128, 0, 128, 1],
64 'red': [255, 0, 0, 1], 'rosybrown': [188, 143, 143, 1],
65 'royalblue': [65, 105, 225, 1], 'saddlebrown': [139, 69, 19, 1],
66 'salmon': [250, 128, 114, 1], 'sandybrown': [244, 164, 96, 1],
67 'seagreen': [46, 139, 87, 1], 'seashell': [255, 245, 238, 1],
68 'sienna': [160, 82, 45, 1], 'silver': [192, 192, 192, 1],
69 'skyblue': [135, 206, 235, 1], 'slateblue': [106, 90, 205, 1],
70 'slategray': [112, 128, 144, 1], 'slategrey': [112, 128, 144, 1],
71 'snow': [255, 250, 250, 1], 'springgreen': [0, 255, 127, 1],
72 'steelblue': [70, 130, 180, 1], 'tan': [210, 180, 140, 1],
73 'teal': [0, 128, 128, 1], 'thistle': [216, 191, 216, 1],
74 'tomato': [255, 99, 71, 1], 'turquoise': [64, 224, 208, 1],
75 'violet': [238, 130, 238, 1], 'wheat': [245, 222, 179, 1],
76 'white': [255, 255, 255, 1], 'whitesmoke': [245, 245, 245, 1],
77 'yellow': [255, 255, 0, 1], 'yellowgreen': [154, 205, 50, 1]
78};
79function clampCssByte(i) {
80 i = Math.round(i);
81 return i < 0 ? 0 : i > 255 ? 255 : i;
82}
83function clampCssAngle(i) {
84 i = Math.round(i);
85 return i < 0 ? 0 : i > 360 ? 360 : i;
86}
87function clampCssFloat(f) {
88 return f < 0 ? 0 : f > 1 ? 1 : f;
89}
90function parseCssInt(val) {
91 var str = val;
92 if (str.length && str.charAt(str.length - 1) === '%') {
93 return clampCssByte(parseFloat(str) / 100 * 255);
94 }
95 return clampCssByte(parseInt(str, 10));
96}
97function parseCssFloat(val) {
98 var str = val;
99 if (str.length && str.charAt(str.length - 1) === '%') {
100 return clampCssFloat(parseFloat(str) / 100);
101 }
102 return clampCssFloat(parseFloat(str));
103}
104function cssHueToRgb(m1, m2, h) {
105 if (h < 0) {
106 h += 1;
107 }
108 else if (h > 1) {
109 h -= 1;
110 }
111 if (h * 6 < 1) {
112 return m1 + (m2 - m1) * h * 6;
113 }
114 if (h * 2 < 1) {
115 return m2;
116 }
117 if (h * 3 < 2) {
118 return m1 + (m2 - m1) * (2 / 3 - h) * 6;
119 }
120 return m1;
121}
122function lerpNumber(a, b, p) {
123 return a + (b - a) * p;
124}
125function setRgba(out, r, g, b, a) {
126 out[0] = r;
127 out[1] = g;
128 out[2] = b;
129 out[3] = a;
130 return out;
131}
132function copyRgba(out, a) {
133 out[0] = a[0];
134 out[1] = a[1];
135 out[2] = a[2];
136 out[3] = a[3];
137 return out;
138}
139var colorCache = new LRU(20);
140var lastRemovedArr = null;
141function putToCache(colorStr, rgbaArr) {
142 if (lastRemovedArr) {
143 copyRgba(lastRemovedArr, rgbaArr);
144 }
145 lastRemovedArr = colorCache.put(colorStr, lastRemovedArr || (rgbaArr.slice()));
146}
147export function parse(colorStr, rgbaArr) {
148 if (!colorStr) {
149 return;
150 }
151 rgbaArr = rgbaArr || [];
152 var cached = colorCache.get(colorStr);
153 if (cached) {
154 return copyRgba(rgbaArr, cached);
155 }
156 colorStr = colorStr + '';
157 var str = colorStr.replace(/ /g, '').toLowerCase();
158 if (str in kCSSColorTable) {
159 copyRgba(rgbaArr, kCSSColorTable[str]);
160 putToCache(colorStr, rgbaArr);
161 return rgbaArr;
162 }
163 var strLen = str.length;
164 if (str.charAt(0) === '#') {
165 if (strLen === 4 || strLen === 5) {
166 var iv = parseInt(str.slice(1, 4), 16);
167 if (!(iv >= 0 && iv <= 0xfff)) {
168 setRgba(rgbaArr, 0, 0, 0, 1);
169 return;
170 }
171 setRgba(rgbaArr, ((iv & 0xf00) >> 4) | ((iv & 0xf00) >> 8), (iv & 0xf0) | ((iv & 0xf0) >> 4), (iv & 0xf) | ((iv & 0xf) << 4), strLen === 5 ? parseInt(str.slice(4), 16) / 0xf : 1);
172 putToCache(colorStr, rgbaArr);
173 return rgbaArr;
174 }
175 else if (strLen === 7 || strLen === 9) {
176 var iv = parseInt(str.slice(1, 7), 16);
177 if (!(iv >= 0 && iv <= 0xffffff)) {
178 setRgba(rgbaArr, 0, 0, 0, 1);
179 return;
180 }
181 setRgba(rgbaArr, (iv & 0xff0000) >> 16, (iv & 0xff00) >> 8, iv & 0xff, strLen === 9 ? parseInt(str.slice(7), 16) / 0xff : 1);
182 putToCache(colorStr, rgbaArr);
183 return rgbaArr;
184 }
185 return;
186 }
187 var op = str.indexOf('(');
188 var ep = str.indexOf(')');
189 if (op !== -1 && ep + 1 === strLen) {
190 var fname = str.substr(0, op);
191 var params = str.substr(op + 1, ep - (op + 1)).split(',');
192 var alpha = 1;
193 switch (fname) {
194 case 'rgba':
195 if (params.length !== 4) {
196 return params.length === 3
197 ? setRgba(rgbaArr, +params[0], +params[1], +params[2], 1)
198 : setRgba(rgbaArr, 0, 0, 0, 1);
199 }
200 alpha = parseCssFloat(params.pop());
201 case 'rgb':
202 if (params.length >= 3) {
203 setRgba(rgbaArr, parseCssInt(params[0]), parseCssInt(params[1]), parseCssInt(params[2]), params.length === 3 ? alpha : parseCssFloat(params[3]));
204 putToCache(colorStr, rgbaArr);
205 return rgbaArr;
206 }
207 else {
208 setRgba(rgbaArr, 0, 0, 0, 1);
209 return;
210 }
211 case 'hsla':
212 if (params.length !== 4) {
213 setRgba(rgbaArr, 0, 0, 0, 1);
214 return;
215 }
216 params[3] = parseCssFloat(params[3]);
217 hsla2rgba(params, rgbaArr);
218 putToCache(colorStr, rgbaArr);
219 return rgbaArr;
220 case 'hsl':
221 if (params.length !== 3) {
222 setRgba(rgbaArr, 0, 0, 0, 1);
223 return;
224 }
225 hsla2rgba(params, rgbaArr);
226 putToCache(colorStr, rgbaArr);
227 return rgbaArr;
228 default:
229 return;
230 }
231 }
232 setRgba(rgbaArr, 0, 0, 0, 1);
233 return;
234}
235function hsla2rgba(hsla, rgba) {
236 var h = (((parseFloat(hsla[0]) % 360) + 360) % 360) / 360;
237 var s = parseCssFloat(hsla[1]);
238 var l = parseCssFloat(hsla[2]);
239 var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
240 var m1 = l * 2 - m2;
241 rgba = rgba || [];
242 setRgba(rgba, clampCssByte(cssHueToRgb(m1, m2, h + 1 / 3) * 255), clampCssByte(cssHueToRgb(m1, m2, h) * 255), clampCssByte(cssHueToRgb(m1, m2, h - 1 / 3) * 255), 1);
243 if (hsla.length === 4) {
244 rgba[3] = hsla[3];
245 }
246 return rgba;
247}
248function rgba2hsla(rgba) {
249 if (!rgba) {
250 return;
251 }
252 var R = rgba[0] / 255;
253 var G = rgba[1] / 255;
254 var B = rgba[2] / 255;
255 var vMin = Math.min(R, G, B);
256 var vMax = Math.max(R, G, B);
257 var delta = vMax - vMin;
258 var L = (vMax + vMin) / 2;
259 var H;
260 var S;
261 if (delta === 0) {
262 H = 0;
263 S = 0;
264 }
265 else {
266 if (L < 0.5) {
267 S = delta / (vMax + vMin);
268 }
269 else {
270 S = delta / (2 - vMax - vMin);
271 }
272 var deltaR = (((vMax - R) / 6) + (delta / 2)) / delta;
273 var deltaG = (((vMax - G) / 6) + (delta / 2)) / delta;
274 var deltaB = (((vMax - B) / 6) + (delta / 2)) / delta;
275 if (R === vMax) {
276 H = deltaB - deltaG;
277 }
278 else if (G === vMax) {
279 H = (1 / 3) + deltaR - deltaB;
280 }
281 else if (B === vMax) {
282 H = (2 / 3) + deltaG - deltaR;
283 }
284 if (H < 0) {
285 H += 1;
286 }
287 if (H > 1) {
288 H -= 1;
289 }
290 }
291 var hsla = [H * 360, S, L];
292 if (rgba[3] != null) {
293 hsla.push(rgba[3]);
294 }
295 return hsla;
296}
297export function lift(color, level) {
298 var colorArr = parse(color);
299 if (colorArr) {
300 for (var i = 0; i < 3; i++) {
301 if (level < 0) {
302 colorArr[i] = colorArr[i] * (1 - level) | 0;
303 }
304 else {
305 colorArr[i] = ((255 - colorArr[i]) * level + colorArr[i]) | 0;
306 }
307 if (colorArr[i] > 255) {
308 colorArr[i] = 255;
309 }
310 else if (colorArr[i] < 0) {
311 colorArr[i] = 0;
312 }
313 }
314 return stringify(colorArr, colorArr.length === 4 ? 'rgba' : 'rgb');
315 }
316}
317export function toHex(color) {
318 var colorArr = parse(color);
319 if (colorArr) {
320 return ((1 << 24) + (colorArr[0] << 16) + (colorArr[1] << 8) + (+colorArr[2])).toString(16).slice(1);
321 }
322}
323export function fastLerp(normalizedValue, colors, out) {
324 if (!(colors && colors.length)
325 || !(normalizedValue >= 0 && normalizedValue <= 1)) {
326 return;
327 }
328 out = out || [];
329 var value = normalizedValue * (colors.length - 1);
330 var leftIndex = Math.floor(value);
331 var rightIndex = Math.ceil(value);
332 var leftColor = colors[leftIndex];
333 var rightColor = colors[rightIndex];
334 var dv = value - leftIndex;
335 out[0] = clampCssByte(lerpNumber(leftColor[0], rightColor[0], dv));
336 out[1] = clampCssByte(lerpNumber(leftColor[1], rightColor[1], dv));
337 out[2] = clampCssByte(lerpNumber(leftColor[2], rightColor[2], dv));
338 out[3] = clampCssFloat(lerpNumber(leftColor[3], rightColor[3], dv));
339 return out;
340}
341export var fastMapToColor = fastLerp;
342export function lerp(normalizedValue, colors, fullOutput) {
343 if (!(colors && colors.length)
344 || !(normalizedValue >= 0 && normalizedValue <= 1)) {
345 return;
346 }
347 var value = normalizedValue * (colors.length - 1);
348 var leftIndex = Math.floor(value);
349 var rightIndex = Math.ceil(value);
350 var leftColor = parse(colors[leftIndex]);
351 var rightColor = parse(colors[rightIndex]);
352 var dv = value - leftIndex;
353 var color = stringify([
354 clampCssByte(lerpNumber(leftColor[0], rightColor[0], dv)),
355 clampCssByte(lerpNumber(leftColor[1], rightColor[1], dv)),
356 clampCssByte(lerpNumber(leftColor[2], rightColor[2], dv)),
357 clampCssFloat(lerpNumber(leftColor[3], rightColor[3], dv))
358 ], 'rgba');
359 return fullOutput
360 ? {
361 color: color,
362 leftIndex: leftIndex,
363 rightIndex: rightIndex,
364 value: value
365 }
366 : color;
367}
368export var mapToColor = lerp;
369export function modifyHSL(color, h, s, l) {
370 var colorArr = parse(color);
371 if (color) {
372 colorArr = rgba2hsla(colorArr);
373 h != null && (colorArr[0] = clampCssAngle(h));
374 s != null && (colorArr[1] = parseCssFloat(s));
375 l != null && (colorArr[2] = parseCssFloat(l));
376 return stringify(hsla2rgba(colorArr), 'rgba');
377 }
378}
379export function modifyAlpha(color, alpha) {
380 var colorArr = parse(color);
381 if (colorArr && alpha != null) {
382 colorArr[3] = clampCssFloat(alpha);
383 return stringify(colorArr, 'rgba');
384 }
385}
386export function stringify(arrColor, type) {
387 if (!arrColor || !arrColor.length) {
388 return;
389 }
390 var colorStr = arrColor[0] + ',' + arrColor[1] + ',' + arrColor[2];
391 if (type === 'rgba' || type === 'hsva' || type === 'hsla') {
392 colorStr += ',' + arrColor[3];
393 }
394 return type + '(' + colorStr + ')';
395}
396export function lum(color, backgroundLum) {
397 var arr = parse(color);
398 return arr
399 ? (0.299 * arr[0] + 0.587 * arr[1] + 0.114 * arr[2]) * arr[3] / 255
400 + (1 - arr[3]) * backgroundLum
401 : 0;
402}
403export function random() {
404 return stringify([
405 Math.round(Math.random() * 255),
406 Math.round(Math.random() * 255),
407 Math.round(Math.random() * 255)
408 ], 'rgb');
409}
410var liftedColorCache = new LRU(100);
411export function liftColor(color) {
412 if (isString(color)) {
413 var liftedColor = liftedColorCache.get(color);
414 if (!liftedColor) {
415 liftedColor = lift(color, -0.1);
416 liftedColorCache.put(color, liftedColor);
417 }
418 return liftedColor;
419 }
420 else if (isGradientObject(color)) {
421 var ret = extend({}, color);
422 ret.colorStops = map(color.colorStops, function (stop) { return ({
423 offset: stop.offset,
424 color: lift(stop.color, -0.1)
425 }); });
426 return ret;
427 }
428 return color;
429}