/
color-parser.ts
67 lines (53 loc) 路 2 KB
/
color-parser.ts
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
// Shamelessly stolen from https://github.com/ricokahler/color2k
// We don't need all the color functions but we deeply appreciate their work.
const cache: {
[color: string]: [number, number, number, number];
} = {};
let div: HTMLDivElement | null = null;
function createDiv() {
const d = document.createElement("div");
d.classList.add("color2k-parser");
d.style.opacity = "0";
d.style.pointerEvents = "none";
d.style.position = "fixed";
// div must be mounted for `getComputedStyle` to work
document.body.appendChild(d);
return d;
}
export function parseToRgba(color: string): [number, number, number, number] {
// normalize the color
const normalizedColor = color.toLowerCase().trim();
if (cache[normalizedColor] !== undefined) return cache[normalizedColor];
div = div || createDiv();
div.style.color = "#000";
div.style.color = normalizedColor;
const control = getComputedStyle(div).color;
div.style.color = "#fff";
div.style.color = normalizedColor;
const computedColor = getComputedStyle(div).color;
if (computedColor !== control) throw new Error("Could not parse color");
const result = computedColor
.replace(/[^\d.,]/g, "")
.split(",")
.map(parseFloat) as [number, number, number, number];
if (result.length < 4) {
result.push(1);
}
cache[normalizedColor] = result;
return result;
}
export function withAlpha(color: string, alpha: number): string {
const [r, g, b] = parseToRgba(color);
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}
export function blend(color: string, background: string): string {
const [r, g, b, a] = parseToRgba(color);
if (a === 1) return color;
const [br, bg, bb, ba] = parseToRgba(background);
const ao = a + ba * (1 - a);
// (xaA + xaB路(1鈭抋A))/aR
const ro = (a * r + ba * br * (1 - a)) / ao;
const go = (a * g + ba * bg * (1 - a)) / ao;
const bo = (a * b + ba * bb * (1 - a)) / ao;
return `rgba(${ro}, ${go}, ${bo}, ${ao})`;
}