@etsoo/shared 1.1.15 → 1.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/__tests__/EColor.ts +2 -1
- package/lib/cjs/types/EColor.d.ts +36 -7
- package/lib/cjs/types/EColor.js +115 -15
- package/lib/mjs/types/EColor.d.ts +36 -7
- package/lib/mjs/types/EColor.js +115 -15
- package/package.json +1 -1
- package/src/types/EColor.ts +147 -18
package/README.md
CHANGED
|
@@ -26,7 +26,12 @@ Etsoo implmented Color
|
|
|
26
26
|
|static getColors|Get HEX or RGB colors|
|
|
27
27
|
|static getEColors|Get EColors|
|
|
28
28
|
|static parse|Parse HTML color to EColor|
|
|
29
|
+
|clone|Clone color with adjustments|
|
|
30
|
+
|getContrastRatio|Get contrast ratio, a value between 0 and 1|
|
|
31
|
+
|getDeltaValue|Get Delta value (perceptible by human eyes)|
|
|
32
|
+
|getLuminance|Get luminance|
|
|
29
33
|
|toHEXColor|To HEX color string|
|
|
34
|
+
|toLabValue|To Lab value|
|
|
30
35
|
|toRGBColor|To RGB color string|
|
|
31
36
|
|
|
32
37
|
## Keyboard
|
package/__tests__/EColor.ts
CHANGED
|
@@ -17,17 +17,19 @@ export declare class EColor {
|
|
|
17
17
|
* Get HEX or RGB colors
|
|
18
18
|
* @param init Initial color
|
|
19
19
|
* @param factor Increase factor
|
|
20
|
+
* @param adjustOrder Adjust order to increase difference
|
|
20
21
|
* @param hex to HEX or not
|
|
21
22
|
* @returns Result
|
|
22
23
|
*/
|
|
23
|
-
static getColors(init?: string, factor?: number, hex?: boolean): string[];
|
|
24
|
+
static getColors(init?: string, factor?: number, adjustOrder?: boolean, hex?: boolean): string[];
|
|
24
25
|
/**
|
|
25
26
|
* Get EColors
|
|
26
27
|
* @param init Initial color
|
|
27
28
|
* @param factor Increase factor
|
|
29
|
+
* @param adjustOrder Adjust order to increase difference
|
|
28
30
|
* @returns Result
|
|
29
31
|
*/
|
|
30
|
-
static getEColors(init?: string, factor?: number): EColor[];
|
|
32
|
+
static getEColors(init?: string, factor?: number, adjustOrder?: boolean): EColor[];
|
|
31
33
|
/**
|
|
32
34
|
* HEX string to integer value
|
|
33
35
|
* @param hex HEX string
|
|
@@ -55,7 +57,7 @@ export declare class EColor {
|
|
|
55
57
|
*/
|
|
56
58
|
constructor(r: number, g: number, b: number, alpha?: number | undefined);
|
|
57
59
|
/**
|
|
58
|
-
* Clone color with
|
|
60
|
+
* Clone color with adjustments
|
|
59
61
|
* @param adjustR Adjust R value
|
|
60
62
|
* @param adjustG Adjust G value
|
|
61
63
|
* @param adjustB Adjust B value
|
|
@@ -63,14 +65,41 @@ export declare class EColor {
|
|
|
63
65
|
*/
|
|
64
66
|
clone(adjustR?: number, adjustG?: number, adjustB?: number, alpha?: number): EColor | undefined;
|
|
65
67
|
/**
|
|
66
|
-
*
|
|
67
|
-
* @param
|
|
68
|
-
* @returns RGB color string
|
|
68
|
+
* Get contrast ratio, a value between 0 and 1
|
|
69
|
+
* @param color Contrast color
|
|
69
70
|
*/
|
|
70
|
-
|
|
71
|
+
getContrastRatio(color: EColor): number;
|
|
72
|
+
/**
|
|
73
|
+
* Get Delta value (perceptible by human eyes)
|
|
74
|
+
* <= 1, Not perceptible by human eyes
|
|
75
|
+
* 1 - 2, Perceptible through close observation
|
|
76
|
+
* 2 - 10, Perceptible at a glance
|
|
77
|
+
* 11 - 49, Colors are more similar than opposite
|
|
78
|
+
* 100+, Colors are exact opposite
|
|
79
|
+
* @param color Contrast color
|
|
80
|
+
* @returns Value
|
|
81
|
+
*/
|
|
82
|
+
getDeltaValue(color: EColor): number;
|
|
83
|
+
/**
|
|
84
|
+
* Get luminance
|
|
85
|
+
* Darker one has higher luminance
|
|
86
|
+
* https://dev.to/alvaromontoro/building-your-own-color-contrast-checker-4j7o
|
|
87
|
+
*/
|
|
88
|
+
getLuminance(): number;
|
|
71
89
|
/**
|
|
72
90
|
* To HEX color string
|
|
73
91
|
* @returns HEX color string
|
|
74
92
|
*/
|
|
75
93
|
toHEXColor(): string;
|
|
94
|
+
/**
|
|
95
|
+
* To Lab value
|
|
96
|
+
* @returns Lab value
|
|
97
|
+
*/
|
|
98
|
+
toLabValue(): [number, number, number];
|
|
99
|
+
/**
|
|
100
|
+
* To RGB color string
|
|
101
|
+
* @param includeAlpha Include alpha or not
|
|
102
|
+
* @returns RGB color string
|
|
103
|
+
*/
|
|
104
|
+
toRGBColor(includeAlpha?: boolean): string;
|
|
76
105
|
}
|
package/lib/cjs/types/EColor.js
CHANGED
|
@@ -36,19 +36,21 @@ class EColor {
|
|
|
36
36
|
* Get HEX or RGB colors
|
|
37
37
|
* @param init Initial color
|
|
38
38
|
* @param factor Increase factor
|
|
39
|
+
* @param adjustOrder Adjust order to increase difference
|
|
39
40
|
* @param hex to HEX or not
|
|
40
41
|
* @returns Result
|
|
41
42
|
*/
|
|
42
|
-
static getColors(init = '#000', factor = 51, hex = true) {
|
|
43
|
-
return EColor.getEColors(init, factor).map((c) => hex ? c.toHEXColor() : c.toRGBColor());
|
|
43
|
+
static getColors(init = '#000', factor = 51, adjustOrder = true, hex = true) {
|
|
44
|
+
return EColor.getEColors(init, factor, adjustOrder).map((c) => hex ? c.toHEXColor() : c.toRGBColor());
|
|
44
45
|
}
|
|
45
46
|
/**
|
|
46
47
|
* Get EColors
|
|
47
48
|
* @param init Initial color
|
|
48
49
|
* @param factor Increase factor
|
|
50
|
+
* @param adjustOrder Adjust order to increase difference
|
|
49
51
|
* @returns Result
|
|
50
52
|
*/
|
|
51
|
-
static getEColors(init = '#000', factor = 51) {
|
|
53
|
+
static getEColors(init = '#000', factor = 51, adjustOrder = true) {
|
|
52
54
|
var _a;
|
|
53
55
|
// Init color
|
|
54
56
|
const initColor = (_a = EColor.parse(init)) !== null && _a !== void 0 ? _a : new EColor(0, 0, 0);
|
|
@@ -65,13 +67,38 @@ class EColor {
|
|
|
65
67
|
for (const r of factors) {
|
|
66
68
|
for (const g of factors) {
|
|
67
69
|
for (const b of factors) {
|
|
68
|
-
|
|
69
|
-
if (newColor)
|
|
70
|
-
colors.push(newColor);
|
|
70
|
+
colors.push(initColor.clone(r, g, b));
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
|
-
|
|
74
|
+
// Non-nullable colors
|
|
75
|
+
const nColors = colors.filter((color) => color != null);
|
|
76
|
+
// Adjust order
|
|
77
|
+
if (adjustOrder) {
|
|
78
|
+
const firstColor = nColors.shift();
|
|
79
|
+
if (firstColor) {
|
|
80
|
+
let color = firstColor;
|
|
81
|
+
const newColors = [color];
|
|
82
|
+
while (nColors.length > 0) {
|
|
83
|
+
const result = nColors.reduce((p, c, index) => {
|
|
84
|
+
const delta = color.getDeltaValue(c);
|
|
85
|
+
if (delta != null && delta > p.delta) {
|
|
86
|
+
p.delta = delta;
|
|
87
|
+
p.color = c;
|
|
88
|
+
p.index = index;
|
|
89
|
+
}
|
|
90
|
+
return p;
|
|
91
|
+
}, { delta: 0, color, index: -1 });
|
|
92
|
+
if (result.delta > 0) {
|
|
93
|
+
color = result.color;
|
|
94
|
+
newColors.push(color);
|
|
95
|
+
nColors.splice(result.index, 1);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return newColors;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return nColors;
|
|
75
102
|
}
|
|
76
103
|
/**
|
|
77
104
|
* HEX string to integer value
|
|
@@ -124,7 +151,7 @@ class EColor {
|
|
|
124
151
|
return undefined;
|
|
125
152
|
}
|
|
126
153
|
/**
|
|
127
|
-
* Clone color with
|
|
154
|
+
* Clone color with adjustments
|
|
128
155
|
* @param adjustR Adjust R value
|
|
129
156
|
* @param adjustG Adjust G value
|
|
130
157
|
* @param adjustB Adjust B value
|
|
@@ -141,6 +168,86 @@ class EColor {
|
|
|
141
168
|
return undefined;
|
|
142
169
|
return new EColor(r, g, b, alpha);
|
|
143
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* Get contrast ratio, a value between 0 and 1
|
|
173
|
+
* @param color Contrast color
|
|
174
|
+
*/
|
|
175
|
+
getContrastRatio(color) {
|
|
176
|
+
const lum1 = this.getLuminance();
|
|
177
|
+
const lum2 = color.getLuminance();
|
|
178
|
+
const brightest = Math.max(lum1, lum2);
|
|
179
|
+
const darkest = Math.min(lum1, lum2);
|
|
180
|
+
return (brightest + 0.05) / (darkest + 0.05);
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Get Delta value (perceptible by human eyes)
|
|
184
|
+
* <= 1, Not perceptible by human eyes
|
|
185
|
+
* 1 - 2, Perceptible through close observation
|
|
186
|
+
* 2 - 10, Perceptible at a glance
|
|
187
|
+
* 11 - 49, Colors are more similar than opposite
|
|
188
|
+
* 100+, Colors are exact opposite
|
|
189
|
+
* @param color Contrast color
|
|
190
|
+
* @returns Value
|
|
191
|
+
*/
|
|
192
|
+
getDeltaValue(color) {
|
|
193
|
+
const labA = this.toLabValue();
|
|
194
|
+
const labB = color.toLabValue();
|
|
195
|
+
const deltaL = labA[0] - labB[0];
|
|
196
|
+
const deltaA = labA[1] - labB[1];
|
|
197
|
+
const deltaB = labA[2] - labB[2];
|
|
198
|
+
const c1 = Math.sqrt(labA[1] * labA[1] + labA[2] * labA[2]);
|
|
199
|
+
const c2 = Math.sqrt(labB[1] * labB[1] + labB[2] * labB[2]);
|
|
200
|
+
const deltaC = c1 - c2;
|
|
201
|
+
let deltaH = deltaA * deltaA + deltaB * deltaB - deltaC * deltaC;
|
|
202
|
+
deltaH = deltaH < 0 ? 0 : Math.sqrt(deltaH);
|
|
203
|
+
const sc = 1.0 + 0.045 * c1;
|
|
204
|
+
const sh = 1.0 + 0.015 * c1;
|
|
205
|
+
const deltaLKlsl = deltaL / 1.0;
|
|
206
|
+
const deltaCkcsc = deltaC / sc;
|
|
207
|
+
const deltaHkhsh = deltaH / sh;
|
|
208
|
+
const i = deltaLKlsl * deltaLKlsl +
|
|
209
|
+
deltaCkcsc * deltaCkcsc +
|
|
210
|
+
deltaHkhsh * deltaHkhsh;
|
|
211
|
+
return i < 0 ? 0 : Math.sqrt(i);
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Get luminance
|
|
215
|
+
* Darker one has higher luminance
|
|
216
|
+
* https://dev.to/alvaromontoro/building-your-own-color-contrast-checker-4j7o
|
|
217
|
+
*/
|
|
218
|
+
getLuminance() {
|
|
219
|
+
const a = [this.r, this.g, this.b].map((v) => {
|
|
220
|
+
v /= 255;
|
|
221
|
+
return v <= 0.03928
|
|
222
|
+
? v / 12.92
|
|
223
|
+
: Math.pow((v + 0.055) / 1.055, 2.4);
|
|
224
|
+
});
|
|
225
|
+
return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* To HEX color string
|
|
229
|
+
* @returns HEX color string
|
|
230
|
+
*/
|
|
231
|
+
toHEXColor() {
|
|
232
|
+
return `#${EColor.toHex(this.r)}${EColor.toHex(this.g)}${EColor.toHex(this.b)}`;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* To Lab value
|
|
236
|
+
* @returns Lab value
|
|
237
|
+
*/
|
|
238
|
+
toLabValue() {
|
|
239
|
+
let r = this.r / 255, g = this.g / 255, b = this.b / 255, x, y, z;
|
|
240
|
+
r = r > 0.04045 ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92;
|
|
241
|
+
g = g > 0.04045 ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92;
|
|
242
|
+
b = b > 0.04045 ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92;
|
|
243
|
+
x = (r * 0.4124 + g * 0.3576 + b * 0.1805) / 0.95047;
|
|
244
|
+
y = (r * 0.2126 + g * 0.7152 + b * 0.0722) / 1.0;
|
|
245
|
+
z = (r * 0.0193 + g * 0.1192 + b * 0.9505) / 1.08883;
|
|
246
|
+
x = x > 0.008856 ? Math.pow(x, 1 / 3) : 7.787 * x + 16 / 116;
|
|
247
|
+
y = y > 0.008856 ? Math.pow(y, 1 / 3) : 7.787 * y + 16 / 116;
|
|
248
|
+
z = z > 0.008856 ? Math.pow(z, 1 / 3) : 7.787 * z + 16 / 116;
|
|
249
|
+
return [116 * y - 16, 500 * (x - y), 200 * (y - z)];
|
|
250
|
+
}
|
|
144
251
|
/**
|
|
145
252
|
* To RGB color string
|
|
146
253
|
* @param includeAlpha Include alpha or not
|
|
@@ -154,12 +261,5 @@ class EColor {
|
|
|
154
261
|
return `RGBA(${this.r}, ${this.g}, ${this.b}, ${(_a = this.alpha) !== null && _a !== void 0 ? _a : 1})`;
|
|
155
262
|
return `RGB(${this.r}, ${this.g}, ${this.b})`;
|
|
156
263
|
}
|
|
157
|
-
/**
|
|
158
|
-
* To HEX color string
|
|
159
|
-
* @returns HEX color string
|
|
160
|
-
*/
|
|
161
|
-
toHEXColor() {
|
|
162
|
-
return `#${EColor.toHex(this.r)}${EColor.toHex(this.g)}${EColor.toHex(this.b)}`;
|
|
163
|
-
}
|
|
164
264
|
}
|
|
165
265
|
exports.EColor = EColor;
|
|
@@ -17,17 +17,19 @@ export declare class EColor {
|
|
|
17
17
|
* Get HEX or RGB colors
|
|
18
18
|
* @param init Initial color
|
|
19
19
|
* @param factor Increase factor
|
|
20
|
+
* @param adjustOrder Adjust order to increase difference
|
|
20
21
|
* @param hex to HEX or not
|
|
21
22
|
* @returns Result
|
|
22
23
|
*/
|
|
23
|
-
static getColors(init?: string, factor?: number, hex?: boolean): string[];
|
|
24
|
+
static getColors(init?: string, factor?: number, adjustOrder?: boolean, hex?: boolean): string[];
|
|
24
25
|
/**
|
|
25
26
|
* Get EColors
|
|
26
27
|
* @param init Initial color
|
|
27
28
|
* @param factor Increase factor
|
|
29
|
+
* @param adjustOrder Adjust order to increase difference
|
|
28
30
|
* @returns Result
|
|
29
31
|
*/
|
|
30
|
-
static getEColors(init?: string, factor?: number): EColor[];
|
|
32
|
+
static getEColors(init?: string, factor?: number, adjustOrder?: boolean): EColor[];
|
|
31
33
|
/**
|
|
32
34
|
* HEX string to integer value
|
|
33
35
|
* @param hex HEX string
|
|
@@ -55,7 +57,7 @@ export declare class EColor {
|
|
|
55
57
|
*/
|
|
56
58
|
constructor(r: number, g: number, b: number, alpha?: number | undefined);
|
|
57
59
|
/**
|
|
58
|
-
* Clone color with
|
|
60
|
+
* Clone color with adjustments
|
|
59
61
|
* @param adjustR Adjust R value
|
|
60
62
|
* @param adjustG Adjust G value
|
|
61
63
|
* @param adjustB Adjust B value
|
|
@@ -63,14 +65,41 @@ export declare class EColor {
|
|
|
63
65
|
*/
|
|
64
66
|
clone(adjustR?: number, adjustG?: number, adjustB?: number, alpha?: number): EColor | undefined;
|
|
65
67
|
/**
|
|
66
|
-
*
|
|
67
|
-
* @param
|
|
68
|
-
* @returns RGB color string
|
|
68
|
+
* Get contrast ratio, a value between 0 and 1
|
|
69
|
+
* @param color Contrast color
|
|
69
70
|
*/
|
|
70
|
-
|
|
71
|
+
getContrastRatio(color: EColor): number;
|
|
72
|
+
/**
|
|
73
|
+
* Get Delta value (perceptible by human eyes)
|
|
74
|
+
* <= 1, Not perceptible by human eyes
|
|
75
|
+
* 1 - 2, Perceptible through close observation
|
|
76
|
+
* 2 - 10, Perceptible at a glance
|
|
77
|
+
* 11 - 49, Colors are more similar than opposite
|
|
78
|
+
* 100+, Colors are exact opposite
|
|
79
|
+
* @param color Contrast color
|
|
80
|
+
* @returns Value
|
|
81
|
+
*/
|
|
82
|
+
getDeltaValue(color: EColor): number;
|
|
83
|
+
/**
|
|
84
|
+
* Get luminance
|
|
85
|
+
* Darker one has higher luminance
|
|
86
|
+
* https://dev.to/alvaromontoro/building-your-own-color-contrast-checker-4j7o
|
|
87
|
+
*/
|
|
88
|
+
getLuminance(): number;
|
|
71
89
|
/**
|
|
72
90
|
* To HEX color string
|
|
73
91
|
* @returns HEX color string
|
|
74
92
|
*/
|
|
75
93
|
toHEXColor(): string;
|
|
94
|
+
/**
|
|
95
|
+
* To Lab value
|
|
96
|
+
* @returns Lab value
|
|
97
|
+
*/
|
|
98
|
+
toLabValue(): [number, number, number];
|
|
99
|
+
/**
|
|
100
|
+
* To RGB color string
|
|
101
|
+
* @param includeAlpha Include alpha or not
|
|
102
|
+
* @returns RGB color string
|
|
103
|
+
*/
|
|
104
|
+
toRGBColor(includeAlpha?: boolean): string;
|
|
76
105
|
}
|
package/lib/mjs/types/EColor.js
CHANGED
|
@@ -33,19 +33,21 @@ export class EColor {
|
|
|
33
33
|
* Get HEX or RGB colors
|
|
34
34
|
* @param init Initial color
|
|
35
35
|
* @param factor Increase factor
|
|
36
|
+
* @param adjustOrder Adjust order to increase difference
|
|
36
37
|
* @param hex to HEX or not
|
|
37
38
|
* @returns Result
|
|
38
39
|
*/
|
|
39
|
-
static getColors(init = '#000', factor = 51, hex = true) {
|
|
40
|
-
return EColor.getEColors(init, factor).map((c) => hex ? c.toHEXColor() : c.toRGBColor());
|
|
40
|
+
static getColors(init = '#000', factor = 51, adjustOrder = true, hex = true) {
|
|
41
|
+
return EColor.getEColors(init, factor, adjustOrder).map((c) => hex ? c.toHEXColor() : c.toRGBColor());
|
|
41
42
|
}
|
|
42
43
|
/**
|
|
43
44
|
* Get EColors
|
|
44
45
|
* @param init Initial color
|
|
45
46
|
* @param factor Increase factor
|
|
47
|
+
* @param adjustOrder Adjust order to increase difference
|
|
46
48
|
* @returns Result
|
|
47
49
|
*/
|
|
48
|
-
static getEColors(init = '#000', factor = 51) {
|
|
50
|
+
static getEColors(init = '#000', factor = 51, adjustOrder = true) {
|
|
49
51
|
var _a;
|
|
50
52
|
// Init color
|
|
51
53
|
const initColor = (_a = EColor.parse(init)) !== null && _a !== void 0 ? _a : new EColor(0, 0, 0);
|
|
@@ -62,13 +64,38 @@ export class EColor {
|
|
|
62
64
|
for (const r of factors) {
|
|
63
65
|
for (const g of factors) {
|
|
64
66
|
for (const b of factors) {
|
|
65
|
-
|
|
66
|
-
if (newColor)
|
|
67
|
-
colors.push(newColor);
|
|
67
|
+
colors.push(initColor.clone(r, g, b));
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
}
|
|
71
|
-
|
|
71
|
+
// Non-nullable colors
|
|
72
|
+
const nColors = colors.filter((color) => color != null);
|
|
73
|
+
// Adjust order
|
|
74
|
+
if (adjustOrder) {
|
|
75
|
+
const firstColor = nColors.shift();
|
|
76
|
+
if (firstColor) {
|
|
77
|
+
let color = firstColor;
|
|
78
|
+
const newColors = [color];
|
|
79
|
+
while (nColors.length > 0) {
|
|
80
|
+
const result = nColors.reduce((p, c, index) => {
|
|
81
|
+
const delta = color.getDeltaValue(c);
|
|
82
|
+
if (delta != null && delta > p.delta) {
|
|
83
|
+
p.delta = delta;
|
|
84
|
+
p.color = c;
|
|
85
|
+
p.index = index;
|
|
86
|
+
}
|
|
87
|
+
return p;
|
|
88
|
+
}, { delta: 0, color, index: -1 });
|
|
89
|
+
if (result.delta > 0) {
|
|
90
|
+
color = result.color;
|
|
91
|
+
newColors.push(color);
|
|
92
|
+
nColors.splice(result.index, 1);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return newColors;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return nColors;
|
|
72
99
|
}
|
|
73
100
|
/**
|
|
74
101
|
* HEX string to integer value
|
|
@@ -121,7 +148,7 @@ export class EColor {
|
|
|
121
148
|
return undefined;
|
|
122
149
|
}
|
|
123
150
|
/**
|
|
124
|
-
* Clone color with
|
|
151
|
+
* Clone color with adjustments
|
|
125
152
|
* @param adjustR Adjust R value
|
|
126
153
|
* @param adjustG Adjust G value
|
|
127
154
|
* @param adjustB Adjust B value
|
|
@@ -138,6 +165,86 @@ export class EColor {
|
|
|
138
165
|
return undefined;
|
|
139
166
|
return new EColor(r, g, b, alpha);
|
|
140
167
|
}
|
|
168
|
+
/**
|
|
169
|
+
* Get contrast ratio, a value between 0 and 1
|
|
170
|
+
* @param color Contrast color
|
|
171
|
+
*/
|
|
172
|
+
getContrastRatio(color) {
|
|
173
|
+
const lum1 = this.getLuminance();
|
|
174
|
+
const lum2 = color.getLuminance();
|
|
175
|
+
const brightest = Math.max(lum1, lum2);
|
|
176
|
+
const darkest = Math.min(lum1, lum2);
|
|
177
|
+
return (brightest + 0.05) / (darkest + 0.05);
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Get Delta value (perceptible by human eyes)
|
|
181
|
+
* <= 1, Not perceptible by human eyes
|
|
182
|
+
* 1 - 2, Perceptible through close observation
|
|
183
|
+
* 2 - 10, Perceptible at a glance
|
|
184
|
+
* 11 - 49, Colors are more similar than opposite
|
|
185
|
+
* 100+, Colors are exact opposite
|
|
186
|
+
* @param color Contrast color
|
|
187
|
+
* @returns Value
|
|
188
|
+
*/
|
|
189
|
+
getDeltaValue(color) {
|
|
190
|
+
const labA = this.toLabValue();
|
|
191
|
+
const labB = color.toLabValue();
|
|
192
|
+
const deltaL = labA[0] - labB[0];
|
|
193
|
+
const deltaA = labA[1] - labB[1];
|
|
194
|
+
const deltaB = labA[2] - labB[2];
|
|
195
|
+
const c1 = Math.sqrt(labA[1] * labA[1] + labA[2] * labA[2]);
|
|
196
|
+
const c2 = Math.sqrt(labB[1] * labB[1] + labB[2] * labB[2]);
|
|
197
|
+
const deltaC = c1 - c2;
|
|
198
|
+
let deltaH = deltaA * deltaA + deltaB * deltaB - deltaC * deltaC;
|
|
199
|
+
deltaH = deltaH < 0 ? 0 : Math.sqrt(deltaH);
|
|
200
|
+
const sc = 1.0 + 0.045 * c1;
|
|
201
|
+
const sh = 1.0 + 0.015 * c1;
|
|
202
|
+
const deltaLKlsl = deltaL / 1.0;
|
|
203
|
+
const deltaCkcsc = deltaC / sc;
|
|
204
|
+
const deltaHkhsh = deltaH / sh;
|
|
205
|
+
const i = deltaLKlsl * deltaLKlsl +
|
|
206
|
+
deltaCkcsc * deltaCkcsc +
|
|
207
|
+
deltaHkhsh * deltaHkhsh;
|
|
208
|
+
return i < 0 ? 0 : Math.sqrt(i);
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Get luminance
|
|
212
|
+
* Darker one has higher luminance
|
|
213
|
+
* https://dev.to/alvaromontoro/building-your-own-color-contrast-checker-4j7o
|
|
214
|
+
*/
|
|
215
|
+
getLuminance() {
|
|
216
|
+
const a = [this.r, this.g, this.b].map((v) => {
|
|
217
|
+
v /= 255;
|
|
218
|
+
return v <= 0.03928
|
|
219
|
+
? v / 12.92
|
|
220
|
+
: Math.pow((v + 0.055) / 1.055, 2.4);
|
|
221
|
+
});
|
|
222
|
+
return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* To HEX color string
|
|
226
|
+
* @returns HEX color string
|
|
227
|
+
*/
|
|
228
|
+
toHEXColor() {
|
|
229
|
+
return `#${EColor.toHex(this.r)}${EColor.toHex(this.g)}${EColor.toHex(this.b)}`;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* To Lab value
|
|
233
|
+
* @returns Lab value
|
|
234
|
+
*/
|
|
235
|
+
toLabValue() {
|
|
236
|
+
let r = this.r / 255, g = this.g / 255, b = this.b / 255, x, y, z;
|
|
237
|
+
r = r > 0.04045 ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92;
|
|
238
|
+
g = g > 0.04045 ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92;
|
|
239
|
+
b = b > 0.04045 ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92;
|
|
240
|
+
x = (r * 0.4124 + g * 0.3576 + b * 0.1805) / 0.95047;
|
|
241
|
+
y = (r * 0.2126 + g * 0.7152 + b * 0.0722) / 1.0;
|
|
242
|
+
z = (r * 0.0193 + g * 0.1192 + b * 0.9505) / 1.08883;
|
|
243
|
+
x = x > 0.008856 ? Math.pow(x, 1 / 3) : 7.787 * x + 16 / 116;
|
|
244
|
+
y = y > 0.008856 ? Math.pow(y, 1 / 3) : 7.787 * y + 16 / 116;
|
|
245
|
+
z = z > 0.008856 ? Math.pow(z, 1 / 3) : 7.787 * z + 16 / 116;
|
|
246
|
+
return [116 * y - 16, 500 * (x - y), 200 * (y - z)];
|
|
247
|
+
}
|
|
141
248
|
/**
|
|
142
249
|
* To RGB color string
|
|
143
250
|
* @param includeAlpha Include alpha or not
|
|
@@ -151,11 +258,4 @@ export class EColor {
|
|
|
151
258
|
return `RGBA(${this.r}, ${this.g}, ${this.b}, ${(_a = this.alpha) !== null && _a !== void 0 ? _a : 1})`;
|
|
152
259
|
return `RGB(${this.r}, ${this.g}, ${this.b})`;
|
|
153
260
|
}
|
|
154
|
-
/**
|
|
155
|
-
* To HEX color string
|
|
156
|
-
* @returns HEX color string
|
|
157
|
-
*/
|
|
158
|
-
toHEXColor() {
|
|
159
|
-
return `#${EColor.toHex(this.r)}${EColor.toHex(this.g)}${EColor.toHex(this.b)}`;
|
|
160
|
-
}
|
|
161
261
|
}
|
package/package.json
CHANGED
package/src/types/EColor.ts
CHANGED
|
@@ -19,11 +19,17 @@ export class EColor {
|
|
|
19
19
|
* Get HEX or RGB colors
|
|
20
20
|
* @param init Initial color
|
|
21
21
|
* @param factor Increase factor
|
|
22
|
+
* @param adjustOrder Adjust order to increase difference
|
|
22
23
|
* @param hex to HEX or not
|
|
23
24
|
* @returns Result
|
|
24
25
|
*/
|
|
25
|
-
static getColors(
|
|
26
|
-
|
|
26
|
+
static getColors(
|
|
27
|
+
init: string = '#000',
|
|
28
|
+
factor: number = 51,
|
|
29
|
+
adjustOrder: boolean = true,
|
|
30
|
+
hex: boolean = true
|
|
31
|
+
) {
|
|
32
|
+
return EColor.getEColors(init, factor, adjustOrder).map((c) =>
|
|
27
33
|
hex ? c.toHEXColor() : c.toRGBColor()
|
|
28
34
|
);
|
|
29
35
|
}
|
|
@@ -32,9 +38,14 @@ export class EColor {
|
|
|
32
38
|
* Get EColors
|
|
33
39
|
* @param init Initial color
|
|
34
40
|
* @param factor Increase factor
|
|
41
|
+
* @param adjustOrder Adjust order to increase difference
|
|
35
42
|
* @returns Result
|
|
36
43
|
*/
|
|
37
|
-
static getEColors(
|
|
44
|
+
static getEColors(
|
|
45
|
+
init: string = '#000',
|
|
46
|
+
factor: number = 51,
|
|
47
|
+
adjustOrder: boolean = true
|
|
48
|
+
): EColor[] {
|
|
38
49
|
// Init color
|
|
39
50
|
const initColor = EColor.parse(init) ?? new EColor(0, 0, 0);
|
|
40
51
|
|
|
@@ -48,18 +59,53 @@ export class EColor {
|
|
|
48
59
|
}
|
|
49
60
|
|
|
50
61
|
// RGB loop
|
|
51
|
-
const colors: EColor[] = [initColor];
|
|
52
|
-
|
|
62
|
+
const colors: (EColor | undefined)[] = [initColor];
|
|
53
63
|
for (const r of factors) {
|
|
54
64
|
for (const g of factors) {
|
|
55
65
|
for (const b of factors) {
|
|
56
|
-
|
|
57
|
-
|
|
66
|
+
colors.push(initColor.clone(r, g, b));
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Non-nullable colors
|
|
72
|
+
const nColors = colors.filter(
|
|
73
|
+
(color): color is EColor => color != null
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
// Adjust order
|
|
77
|
+
if (adjustOrder) {
|
|
78
|
+
const firstColor = nColors.shift();
|
|
79
|
+
if (firstColor) {
|
|
80
|
+
let color = firstColor;
|
|
81
|
+
const newColors: EColor[] = [color];
|
|
82
|
+
|
|
83
|
+
while (nColors.length > 0) {
|
|
84
|
+
const result = nColors.reduce(
|
|
85
|
+
(p, c, index) => {
|
|
86
|
+
const delta = color.getDeltaValue(c);
|
|
87
|
+
if (delta != null && delta > p.delta) {
|
|
88
|
+
p.delta = delta;
|
|
89
|
+
p.color = c;
|
|
90
|
+
p.index = index;
|
|
91
|
+
}
|
|
92
|
+
return p;
|
|
93
|
+
},
|
|
94
|
+
{ delta: 0, color, index: -1 }
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
if (result.delta > 0) {
|
|
98
|
+
color = result.color;
|
|
99
|
+
newColors.push(color);
|
|
100
|
+
nColors.splice(result.index, 1);
|
|
101
|
+
}
|
|
58
102
|
}
|
|
103
|
+
|
|
104
|
+
return newColors;
|
|
59
105
|
}
|
|
60
106
|
}
|
|
61
107
|
|
|
62
|
-
return
|
|
108
|
+
return nColors;
|
|
63
109
|
}
|
|
64
110
|
|
|
65
111
|
/**
|
|
@@ -143,7 +189,7 @@ export class EColor {
|
|
|
143
189
|
) {}
|
|
144
190
|
|
|
145
191
|
/**
|
|
146
|
-
* Clone color with
|
|
192
|
+
* Clone color with adjustments
|
|
147
193
|
* @param adjustR Adjust R value
|
|
148
194
|
* @param adjustG Adjust G value
|
|
149
195
|
* @param adjustB Adjust B value
|
|
@@ -169,18 +215,63 @@ export class EColor {
|
|
|
169
215
|
}
|
|
170
216
|
|
|
171
217
|
/**
|
|
172
|
-
*
|
|
173
|
-
* @param
|
|
174
|
-
* @returns RGB color string
|
|
218
|
+
* Get contrast ratio, a value between 0 and 1
|
|
219
|
+
* @param color Contrast color
|
|
175
220
|
*/
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
221
|
+
getContrastRatio(color: EColor) {
|
|
222
|
+
const lum1 = this.getLuminance();
|
|
223
|
+
const lum2 = color.getLuminance();
|
|
224
|
+
const brightest = Math.max(lum1, lum2);
|
|
225
|
+
const darkest = Math.min(lum1, lum2);
|
|
226
|
+
return (brightest + 0.05) / (darkest + 0.05);
|
|
227
|
+
}
|
|
179
228
|
|
|
180
|
-
|
|
181
|
-
|
|
229
|
+
/**
|
|
230
|
+
* Get Delta value (perceptible by human eyes)
|
|
231
|
+
* <= 1, Not perceptible by human eyes
|
|
232
|
+
* 1 - 2, Perceptible through close observation
|
|
233
|
+
* 2 - 10, Perceptible at a glance
|
|
234
|
+
* 11 - 49, Colors are more similar than opposite
|
|
235
|
+
* 100+, Colors are exact opposite
|
|
236
|
+
* @param color Contrast color
|
|
237
|
+
* @returns Value
|
|
238
|
+
*/
|
|
239
|
+
getDeltaValue(color: EColor) {
|
|
240
|
+
const labA = this.toLabValue();
|
|
241
|
+
const labB = color.toLabValue();
|
|
242
|
+
const deltaL = labA[0] - labB[0];
|
|
243
|
+
const deltaA = labA[1] - labB[1];
|
|
244
|
+
const deltaB = labA[2] - labB[2];
|
|
245
|
+
const c1 = Math.sqrt(labA[1] * labA[1] + labA[2] * labA[2]);
|
|
246
|
+
const c2 = Math.sqrt(labB[1] * labB[1] + labB[2] * labB[2]);
|
|
247
|
+
const deltaC = c1 - c2;
|
|
248
|
+
let deltaH = deltaA * deltaA + deltaB * deltaB - deltaC * deltaC;
|
|
249
|
+
deltaH = deltaH < 0 ? 0 : Math.sqrt(deltaH);
|
|
250
|
+
const sc = 1.0 + 0.045 * c1;
|
|
251
|
+
const sh = 1.0 + 0.015 * c1;
|
|
252
|
+
const deltaLKlsl = deltaL / 1.0;
|
|
253
|
+
const deltaCkcsc = deltaC / sc;
|
|
254
|
+
const deltaHkhsh = deltaH / sh;
|
|
255
|
+
const i =
|
|
256
|
+
deltaLKlsl * deltaLKlsl +
|
|
257
|
+
deltaCkcsc * deltaCkcsc +
|
|
258
|
+
deltaHkhsh * deltaHkhsh;
|
|
259
|
+
return i < 0 ? 0 : Math.sqrt(i);
|
|
260
|
+
}
|
|
182
261
|
|
|
183
|
-
|
|
262
|
+
/**
|
|
263
|
+
* Get luminance
|
|
264
|
+
* Darker one has higher luminance
|
|
265
|
+
* https://dev.to/alvaromontoro/building-your-own-color-contrast-checker-4j7o
|
|
266
|
+
*/
|
|
267
|
+
getLuminance() {
|
|
268
|
+
const a = [this.r, this.g, this.b].map((v) => {
|
|
269
|
+
v /= 255;
|
|
270
|
+
return v <= 0.03928
|
|
271
|
+
? v / 12.92
|
|
272
|
+
: Math.pow((v + 0.055) / 1.055, 2.4);
|
|
273
|
+
});
|
|
274
|
+
return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;
|
|
184
275
|
}
|
|
185
276
|
|
|
186
277
|
/**
|
|
@@ -192,4 +283,42 @@ export class EColor {
|
|
|
192
283
|
this.b
|
|
193
284
|
)}`;
|
|
194
285
|
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* To Lab value
|
|
289
|
+
* @returns Lab value
|
|
290
|
+
*/
|
|
291
|
+
toLabValue(): [number, number, number] {
|
|
292
|
+
let r = this.r / 255,
|
|
293
|
+
g = this.g / 255,
|
|
294
|
+
b = this.b / 255,
|
|
295
|
+
x,
|
|
296
|
+
y,
|
|
297
|
+
z;
|
|
298
|
+
r = r > 0.04045 ? Math.pow((r + 0.055) / 1.055, 2.4) : r / 12.92;
|
|
299
|
+
g = g > 0.04045 ? Math.pow((g + 0.055) / 1.055, 2.4) : g / 12.92;
|
|
300
|
+
b = b > 0.04045 ? Math.pow((b + 0.055) / 1.055, 2.4) : b / 12.92;
|
|
301
|
+
x = (r * 0.4124 + g * 0.3576 + b * 0.1805) / 0.95047;
|
|
302
|
+
y = (r * 0.2126 + g * 0.7152 + b * 0.0722) / 1.0;
|
|
303
|
+
z = (r * 0.0193 + g * 0.1192 + b * 0.9505) / 1.08883;
|
|
304
|
+
x = x > 0.008856 ? Math.pow(x, 1 / 3) : 7.787 * x + 16 / 116;
|
|
305
|
+
y = y > 0.008856 ? Math.pow(y, 1 / 3) : 7.787 * y + 16 / 116;
|
|
306
|
+
z = z > 0.008856 ? Math.pow(z, 1 / 3) : 7.787 * z + 16 / 116;
|
|
307
|
+
return [116 * y - 16, 500 * (x - y), 200 * (y - z)];
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* To RGB color string
|
|
312
|
+
* @param includeAlpha Include alpha or not
|
|
313
|
+
* @returns RGB color string
|
|
314
|
+
*/
|
|
315
|
+
toRGBColor(includeAlpha?: boolean) {
|
|
316
|
+
// Default case
|
|
317
|
+
includeAlpha ??= this.alpha != null;
|
|
318
|
+
|
|
319
|
+
if (includeAlpha)
|
|
320
|
+
return `RGBA(${this.r}, ${this.g}, ${this.b}, ${this.alpha ?? 1})`;
|
|
321
|
+
|
|
322
|
+
return `RGB(${this.r}, ${this.g}, ${this.b})`;
|
|
323
|
+
}
|
|
195
324
|
}
|