-
Notifications
You must be signed in to change notification settings - Fork 0
/
colorCode.js
385 lines (352 loc) · 12.5 KB
/
colorCode.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
var colorCode = class {
constructor(...args) {
if (typeof arguments[0] == 'string') {
return this.hex(...args);
} else {
return this.set(...args);
}
}
// general setter
set(red, green, blue, alpha) {
// color channels
this.red = (red !== undefined) ? red : 0;
this.green = (green !== undefined) ? green : 0;
this.blue = (blue !== undefined) ? blue : 0;
// alpha channel
this.alpha = (alpha !== undefined) ? alpha : undefined;
// return object
return this;
}
// get or parse HEX code
hex(hex) {
if (hex !== undefined) {
return this.parseHex(hex);
} else {
return this.getHex();
}
}
// get or parse RGB code
rgb(rgb) {
if (rgb !== undefined) {
return this.parseRgb(rgb);
} else {
return this.getRgb();
}
}
// get hsl
hsl() {
return getHsl();
}
// compare with another colorCode object
// returns difference in hue, saturation and lightness in percentages
// helps you transform color A into B through hue, saturation and lightness operations in scss
relativeHslTo(object) {
var a = this.rgbToHsl(this.red, this.green, this.blue);
var b = object.rgbToHsl(object.red, object.green, object.blue);
var diff = [];
diff[0] = (parseInt(b[0]) - parseInt(a[0])) + 'deg';
diff[1] = (parseInt(b[1]) - parseInt(a[1])) + '%';
diff[2] = (parseInt(b[2]) - parseInt(a[2])) + '%';
return diff;
}
// compare with another colorCode object
// returns SCSS color operations to transform color into another color
// @param variationColor colorCode object
// @param colorVariable string used to reference color, equals base color HEX by default
scssTransformTo(variationColor, colorVariable) {
// get baseColor
var baseColor = this.hex();
var diff = this.relativeHslTo(variationColor);
// use color variable
if (colorVariable !== undefined) {
// start output
var output = colorVariable;
} else {
// start output
var output = '#' + baseColor.replace("#", "");
}
// hue
if (parseInt(diff[0]) !== 0) {
output = 'adjust-hue(' + output + ',' + diff[0] + ')';
}
// saturation
if (parseInt(diff[1]) > 0) {
output = 'saturate(' + output + ',' + diff[1] + ')';
} else if (parseInt(diff[1]) < 0) {
output = 'desaturate(' + output + ',' + diff[1].replace(/-/g, '') + ')';
}
// lightness
if (parseInt(diff[2]) > 0) {
output = 'lighten(' + output + ',' + diff[2] + ')';
} else if (parseInt(diff[2]) < 0) {
output = 'darken(' + output + ',' + diff[2].replace(/-/g, '') + ')';
}
return output + ';';
}
// returns SCSS color operations to transform color by provided HSL values
// @param diff array from relativeHslTo()
// @param colorString string used to reference color, equals base color HEX by default
scssTransformBy(diff, colorVariable) {
// get baseColor
var baseColor = this.hex();
// use color variable
if (colorVariable !== undefined) {
// start output
var output = colorVariable;
} else {
// start output
var output = '#' + baseColor.replace("#", "");
}
// hue
if (parseInt(diff[0]) !== 0) {
output = 'adjust-hue(' + output + ',' + diff[0] + ')';
}
// saturation
if (parseInt(diff[1]) > 0) {
output = 'saturate(' + output + ',' + diff[1] + ')';
} else if (parseInt(diff[1]) < 0) {
output = 'desaturate(' + output + ',' + diff[1].replace(/-/g, '') + ')';
}
// lightness
if (parseInt(diff[2]) > 0) {
output = 'lighten(' + output + ',' + diff[2] + ')';
} else if (parseInt(diff[2]) < 0) {
output = 'darken(' + output + ',' + diff[2].replace(/-/g, '') + ')';
}
return output + ';';
}
// parse HEX string to set properties
parseHex(hex) {
// removing pound symbol if present
hex = hex.replace('#', '');
// 6 and 8 character strings
if (hex.length == 6 || hex.length == 8) {
// splitting channels
var channels = this.splitString(hex, 2);
// setting color channels
this.red = this.hexToNumber(channels[0]);
this.green = this.hexToNumber(channels[1]);
this.blue = this.hexToNumber(channels[2]);
// setting alpha channel if available
this.alpha = (channels[3] !== undefined) ? this.hexToOpacity(channels[3]) : undefined;
// 3 and 4 character shorthand strings
} else if (hex.length == 3 || hex.length == 4) {
// splitting channels
var channels = this.splitString(hex, 1);
// setting color channels
this.red = this.hexToNumber(channels[0] + channels[0]);
this.green = this.hexToNumber(channels[1] + channels[1]);
this.blue = this.hexToNumber(channels[2] + channels[2]);
// setting alpha channel if available
this.alpha = (channels[3] !== undefined) ? this.hexToOpacity(channels[3]) : undefined;
// else throw error
} else {
throw "Invalid HEX string provided to parseHex()! Provided: "+hex;
}
// return object
return this;
}
// parse RGB string to set properties
parseRgb(rgb) {
// if parentheses are present
if (rgb.indexOf('(') > -1) {
// get string between parentheses
rgb = rgb.substring(rgb.lastIndexOf("(")+1,rgb.lastIndexOf(")"));
}
// remove spaces
rgb = rgb.replace(/\s+/g, '');
// explode string into channels
var channels = rgb.split(',');
// if valid number of channels
if (channels.length == 3 || channels.length == 4) {
// setting channels
this.red = parseInt(channels[0]);
this.green = parseInt(channels[1]);
this.blue = parseInt(channels[2]);
// alpha channel
channels[3] = parseFloat(channels[3]);
if (!isNaN(channels[3])) {
this.alpha = this.round(channels[3], 2);
} else {
this.alpha = undefined;
}
// else throw error
} else {
throw "Invalid RGB string provided to parseRgb()";
}
// return object
return this;
}
// returns HEX string
getHex() {
// init output
var output = '';
// rgb channels
var colorChannels = [this.red, this.green, this.blue];
var dedupeFlag = true;
colorChannels.forEach(value => {
output += this.numberToHex(value);
if (!this.isDoubleChar(this.numberToHex(value))) {
dedupeFlag = false;
}
});
// alpha channel
if (this.alpha !== undefined) {
dedupeFlag = false;
output += this.decToHexAlpha(this.alpha);
}
// deduping if possible
if (dedupeFlag) {
output = this.dedupe(output);
}
// prepend pound symbol
output = '#'+output;
return output;
}
// returns CSS RGB or RGBA string
getRgb() {
// function open
var output = (this.alpha !== undefined) ? 'rgba(' : 'rgb(';
output += [this.red, this.green, this.blue].join(',');
output += (this.alpha !== undefined) ? ',' + this.alpha + ')' : ')';
return output;
}
// returns CSS HSL or HSLA string
getHsl() {
var hsl = this.rgbToHsl(this.red, this.green, this.blue);
var output = (this.alpha !== undefined) ? 'hsla(' : 'hsl(';
output += hsl.join(',');
output += (this.alpha !== undefined) ? ',' + this.alpha + ')' : ')';
return output;
}
// returns array with HSL values
getHslArray(format = 'string') {
var hsl = this.rgbToHsl(this.red, this.green, this.blue);
if (format == 'string') {
var output = hsl;
} else if (format == 'integer') {
var output = [];
hsl.forEach(element => {
output.push(parseInt(element));
});
} else if (format == 'decimal') {
var output = [];
output[0] = parseInt(hsl[0]) / 360;
output[1] = parseInt(hsl[1]) / 100;
output[2] = parseInt(hsl[2]) / 100;
}
return output;
}
// number to hex function
numberToHex(number) {
var hex = number.toString(16);
// ensuring output is always at least two chars long
if (hex.length == 1) {
return "0" + hex;
} else {
return hex;
}
}
// decimal to hex alpha
decToHexAlpha(decimal) {
return this.numberToHex(this.round(decimal * 100 * (255 / 100), 0));
}
// simple test function for hexAlpha that outputs the hex codes for 0%-100%
testHexAlpha() {
for (var i=100; i > 0; i -= 1){
console.log(i + "% - " + this.decToHexAlpha(i/100));
}
}
// hex alpha to decimal
hexToOpacity(hex) {
// getting scale
var scale = Math.pow(16, hex.length) - 1;
// calculating decimal value
return this.round(this.hexToNumber(hex) / scale, 2);
}
// hex to number
hexToNumber(hex) {
return parseInt(hex, 16);
}
// easy round function
round(value, precision) {
return Number(Math.round(value+'e'+precision)+'e-'+precision);
}
// explode string into chunks of length, returns array with segments
splitString(string, size) {
return string.match(new RegExp('.{1,' + size + '}', 'g'));
}
// check if HEX value could be single character
isDoubleChar(string) {
return string[0] == string[1];
}
// dedupe function
dedupe(string) {
var chars = string.split('');
for (var i = 1; i < chars.length; i+=2) {
chars[i] = '';
}
return chars.join('');
}
/**
* Converts an RGB color value to HSL. Conversion formula
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
* Assumes r, g, and b are contained in the set [0, 255] and
* returns h, s, and l in the set [0, 1].
*
* @param Number r The red color value
* @param Number g The green color value
* @param Number b The blue color value
* @return Array The HSL representation
*/
rgbToHsl(r, g, b) {
r /= 255, g /= 255, b /= 255;
var max = Math.max(r, g, b), min = Math.min(r, g, b);
var h, s, l = (max + min) / 2;
if (max == min) {
h = s = 0; // achromatic
} else {
var d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
return [((h * 100) / 100 * 360 + 0.5) | 0, ((s * 100 + 0.5) | 0) + '%', ((l * 100 + 0.5) | 0) + '%'];
}
/**
* Converts an HSL color value to RGB. Conversion formula
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
* Assumes h, s, and l are contained in the set [0, 1] and
* returns r, g, and b in the set [0, 255].
*
* @param Number h The hue
* @param Number s The saturation
* @param Number l The lightness
* @return Array The RGB representation
*/
hslToRgb(h, s, l) {
var r, g, b;
if (s == 0) {
r = g = b = l; // achromatic
} else {
function hue2rgb(p, q, t) {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1 / 6) return p + (q - p) * 6 * t;
if (t < 1 / 2) return q;
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
return p;
}
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
var p = 2 * l - q;
r = hue2rgb(p, q, h + 1 / 3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1 / 3);
}
return [r * 255, g * 255, b * 255];
}
}