-
Notifications
You must be signed in to change notification settings - Fork 0
/
ColorStops.ts
56 lines (51 loc) · 1.88 KB
/
ColorStops.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
import { arrayFindIndex } from './CommonUtils';
export type ColorStop = [color: string, percent: number];
export class ColorStops {
private _stops: ColorStop[] = [['transparent', 100]];
constructor() {}
add(color: string, from: number, to: number): void {
from = Math.max(from, 0);
to = Math.min(to, 100);
if (from >= to) {
return;
}
const previousIndex = arrayFindIndex(this._stops, ([, percent]) => from <= percent);
if (previousIndex < 0) {
return;
}
const [previousColor, previousPercent] = this._stops[previousIndex];
const newStops: ColorStop[] = [];
if (from > 0) {
newStops.push([previousColor, from]);
}
newStops.push([color, to]);
if (to < previousPercent) {
// New stop is fully contained within previous stop
// Split previous stop
newStops.push([previousColor, previousPercent]);
this._stops.splice(previousIndex, 1, ...newStops);
} else {
// New stop extends beyond previous stop
// Remove overlapping stops
let nextIndex = previousIndex + 1;
while (nextIndex < this._stops.length) {
if (to < this._stops[nextIndex][1]) {
break;
}
nextIndex++;
}
this._stops.splice(previousIndex, nextIndex - previousIndex, ...newStops);
}
}
toGradientStops(): string {
const gradientStops: string[] = [];
let prevPercent = 0;
for (const [color, percent] of this._stops) {
if (percent < prevPercent) continue;
gradientStops.push(`${color} ${prevPercent}%`);
gradientStops.push(`${color} ${percent}%`);
prevPercent = percent;
}
return gradientStops.join(', ');
}
}