chnobli 0.1.1 → 0.1.3
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/.eslintignore +1 -0
- package/.github/workflows/ci.yaml +14 -1
- package/LICENSE.md +1 -1
- package/docs/INDEX.md +15 -0
- package/jsdoc.conf.json +1 -1
- package/package.json +6 -3
- package/src/animation/animation.js +88 -25
- package/src/animation/property.js +408 -52
- package/src/animation/public.js +72 -2
- package/src/animator.js +2 -0
- package/src/chnobli.js +8 -3
- package/src/responsive/event.js +46 -0
- package/src/responsive/testevent.js +31 -0
- package/src/scroll/event.js +1 -1
- package/src/stagger/stagger.js +5 -8
- package/src/target/basetarget.js +92 -0
- package/src/target/domtarget.js +266 -0
- package/src/target/target.js +22 -0
- package/src/target/testdomnode.js +61 -0
- package/src/tests/properties.test.js +150 -0
- package/src/tests/timeline.test.js +234 -0
- package/src/tests/timing.test.js +270 -0
- package/src/tests/usecases.test.js +64 -0
- package/src/tests/values.test.js +162 -0
- package/src/timeline/public.js +192 -13
- package/src/timeline/timeline.js +76 -22
- package/src/timing/testticker.js +98 -0
- package/src/timing/ticker.js +49 -9
- package/src/timing/timing.js +121 -21
- package/src/utils/events.js +4 -0
- package/src/utils/motionpath.js +3 -0
- package/src/utils/utils.js +22 -2
- package/src/values/colorvalue.js +167 -0
- package/src/values/defaultcolors.js +148 -0
- package/src/values/stylevalue.js +148 -0
- package/src/{utils → values}/value.js +15 -7
- package/src/utils/target.js +0 -145
package/src/timing/timing.js
CHANGED
|
@@ -1,12 +1,28 @@
|
|
|
1
|
-
import Ease from './ease.js';
|
|
2
1
|
import { takeProp } from '../utils/internal.js';
|
|
3
2
|
|
|
4
3
|
export const STATE_BEFORE = 0;
|
|
4
|
+
/// start only occurs if the current position is exactly 0 or 1 if reversed
|
|
5
5
|
export const STATE_START = 1;
|
|
6
6
|
export const STATE_RUNNING = 2;
|
|
7
|
+
/// ended only occurs if the current position is exactly 1 or 0 if reversed
|
|
7
8
|
export const STATE_ENDED = 3;
|
|
8
9
|
export const STATE_AFTER = 4;
|
|
9
10
|
|
|
11
|
+
/**
|
|
12
|
+
* This class handles everything timing related
|
|
13
|
+
*
|
|
14
|
+
* It manages easing, keeps track of where we are at the moment
|
|
15
|
+
*
|
|
16
|
+
* The most important property is position which gives the calculated position
|
|
17
|
+
*
|
|
18
|
+
*
|
|
19
|
+
* Timing works the same as in after effects
|
|
20
|
+
* if the duration is not at least 1ms the position is always 1 and either
|
|
21
|
+
* STATE_BEFORE or STATE_AFTER
|
|
22
|
+
*
|
|
23
|
+
* if the duration is 1ms seek 0 or 1 will always result in position 1
|
|
24
|
+
* because it is like one frame, so it's an image
|
|
25
|
+
*/
|
|
10
26
|
export default class Timing {
|
|
11
27
|
// removes the relevant properties from the props
|
|
12
28
|
|
|
@@ -26,23 +42,49 @@ export default class Timing {
|
|
|
26
42
|
}
|
|
27
43
|
*/
|
|
28
44
|
constructor(props) {
|
|
45
|
+
// these vars are only readonly
|
|
46
|
+
// use functions to update them
|
|
47
|
+
|
|
29
48
|
this.setDuration(props.duration);
|
|
30
49
|
this.ease = props.ease ?? (t => t);
|
|
31
50
|
this.repeat = props.repeat ?? 0;
|
|
32
51
|
this.alternate = props.alternate ?? true;
|
|
33
52
|
this.reversed = props.reversed ?? false;
|
|
34
53
|
|
|
35
|
-
this.position = 0;
|
|
54
|
+
this.position = this.duration > 0 ? 0 : 1;
|
|
36
55
|
this.state = STATE_BEFORE;
|
|
37
56
|
|
|
38
57
|
// progress does not take alternation into account and has no easing
|
|
39
|
-
// this always increments up
|
|
58
|
+
// this always increments up
|
|
40
59
|
this._progress = 0;
|
|
41
|
-
// this._reversed = false;
|
|
42
60
|
|
|
43
61
|
// scrub
|
|
44
62
|
}
|
|
45
63
|
|
|
64
|
+
positionMs() {
|
|
65
|
+
return this.position * this.iterDuration;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// todo find a better name
|
|
69
|
+
/**
|
|
70
|
+
* Returns the position in milliseconds
|
|
71
|
+
*
|
|
72
|
+
* If the state is before or after the position might be more/less than
|
|
73
|
+
* required
|
|
74
|
+
*/
|
|
75
|
+
positionMsUnbounded() {
|
|
76
|
+
const outOfBounds = this.state <= STATE_BEFORE
|
|
77
|
+
|| this.state >= STATE_AFTER;
|
|
78
|
+
|
|
79
|
+
if (!outOfBounds)
|
|
80
|
+
return this.position * this.iterDuration;
|
|
81
|
+
|
|
82
|
+
if (this.position === 0)
|
|
83
|
+
return -1;
|
|
84
|
+
return this.position * this.iterDuration + 1;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/// iterDuration should always be >=0
|
|
46
88
|
setDuration(iterDuration) {
|
|
47
89
|
this.iterDuration = iterDuration;
|
|
48
90
|
|
|
@@ -60,9 +102,23 @@ export default class Timing {
|
|
|
60
102
|
if (this.state >= STATE_AFTER)
|
|
61
103
|
return;
|
|
62
104
|
|
|
105
|
+
if (this.iterDuration <= 0) {
|
|
106
|
+
this._updateProgress(1);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
63
110
|
this._updateProgress(this._progress + change / this.iterDuration);
|
|
64
111
|
}
|
|
65
112
|
|
|
113
|
+
seekMs(ms) {
|
|
114
|
+
if (this.iterDuration <= 0) {
|
|
115
|
+
this._updateProgress(Math.sign(ms));
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
this._updateProgress(ms / this.iterDuration);
|
|
120
|
+
}
|
|
121
|
+
|
|
66
122
|
// should be between 0-1 if outside might change the state
|
|
67
123
|
seek(pos) {
|
|
68
124
|
if (this.repeat <= 0) {
|
|
@@ -73,19 +129,73 @@ export default class Timing {
|
|
|
73
129
|
}
|
|
74
130
|
}
|
|
75
131
|
|
|
132
|
+
savePosition() {
|
|
133
|
+
return {
|
|
134
|
+
progress: this._progress
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
restorePosition(pos) {
|
|
139
|
+
this._updateProgress(pos.progress);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
setAlternate(alternate) {
|
|
143
|
+
if (this.alternate == alternate)
|
|
144
|
+
return;
|
|
145
|
+
|
|
146
|
+
// make sure the reversed is updated according to the current inversion
|
|
147
|
+
this.reversed = alternate == this._shouldInvert();
|
|
148
|
+
this.alternate = alternate;
|
|
149
|
+
}
|
|
150
|
+
|
|
76
151
|
reverse() {
|
|
77
152
|
this.reversed = !this.reversed;
|
|
78
153
|
|
|
79
|
-
|
|
80
|
-
|
|
154
|
+
const wrapAround = p => {
|
|
155
|
+
if (this.repeat > -1)
|
|
156
|
+
return p % (this.repeat + 1);
|
|
157
|
+
return p;
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
let p;
|
|
161
|
+
if (this.state <= STATE_BEFORE) {
|
|
162
|
+
p = 2;
|
|
163
|
+
} else if (this.state >= STATE_AFTER) {
|
|
164
|
+
p = -1;
|
|
165
|
+
// check if the values should be reversed
|
|
166
|
+
} else if (this.reversed != this._shouldInvert()) {
|
|
167
|
+
let decimal = 1 - this._progress % 1;
|
|
168
|
+
p = wrapAround(Math.floor(this._progress) + decimal);
|
|
169
|
+
} else {
|
|
170
|
+
p = wrapAround(this._progress);
|
|
171
|
+
}
|
|
81
172
|
|
|
82
173
|
this._updateProgress(p);
|
|
83
174
|
}
|
|
84
175
|
|
|
176
|
+
_shouldInvert() {
|
|
177
|
+
return this.alternate && Math.floor(this._progress) % 2 === 1;
|
|
178
|
+
}
|
|
179
|
+
|
|
85
180
|
_updateProgress(newProgress) {
|
|
181
|
+
// if duration is zero the position is always 1
|
|
182
|
+
// and the state is either BEFORE or AFTER
|
|
183
|
+
if (this.iterDuration <= 0) {
|
|
184
|
+
newProgress = Math.sign(newProgress);
|
|
185
|
+
this._progress = newProgress;
|
|
186
|
+
this.position = 1;
|
|
187
|
+
|
|
188
|
+
if (newProgress < 0)
|
|
189
|
+
this.state = STATE_BEFORE;
|
|
190
|
+
else
|
|
191
|
+
this.state = STATE_AFTER;
|
|
192
|
+
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
|
|
86
196
|
this._progress = newProgress;
|
|
87
197
|
|
|
88
|
-
// since
|
|
198
|
+
// since infinite repeat can never end let's ignore it
|
|
89
199
|
if (this.repeat > -1) {
|
|
90
200
|
const end = this.repeat + 1;
|
|
91
201
|
if (this._progress > end) {
|
|
@@ -108,21 +218,12 @@ export default class Timing {
|
|
|
108
218
|
this.state = STATE_START;
|
|
109
219
|
}
|
|
110
220
|
|
|
111
|
-
|
|
112
|
-
let reversed = this.reversed;
|
|
113
|
-
|
|
114
|
-
// calc if we are in a reversed iteration or not
|
|
115
|
-
if (this.alternate) {
|
|
116
|
-
let shouldInverse = Math.floor(this._progress) % 2 === 1;
|
|
117
|
-
if (shouldInverse)
|
|
118
|
-
reversed = !reversed;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
221
|
// now calculate the position
|
|
122
|
-
|
|
123
222
|
this.position = this._progress % 1;
|
|
124
223
|
|
|
125
|
-
if
|
|
224
|
+
// calc if we are in a reversed iteration or not
|
|
225
|
+
// and we are we should invert the position
|
|
226
|
+
if (this.reversed != this._shouldInvert())
|
|
126
227
|
this.position = 1 - this.position;
|
|
127
228
|
|
|
128
229
|
this.position = this.ease(this.position);
|
|
@@ -145,10 +246,9 @@ export function parseDuration(dur) {
|
|
|
145
246
|
if (typeof dur !== 'number')
|
|
146
247
|
throw new Error('duration is not a number');
|
|
147
248
|
|
|
148
|
-
// convert s to ms
|
|
149
249
|
dur = Math.round(dur);
|
|
150
250
|
|
|
151
|
-
return Math.max(dur,
|
|
251
|
+
return Math.max(dur, 0);
|
|
152
252
|
}
|
|
153
253
|
|
|
154
254
|
export function parseEase(ease) {
|
package/src/utils/events.js
CHANGED
package/src/utils/motionpath.js
CHANGED
|
@@ -8,6 +8,9 @@ function catmullRom(p0, p1, p2, p3, t, p1Tension, p2Tension) {
|
|
|
8
8
|
t3 + (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Calculates a curve between different points
|
|
13
|
+
*/
|
|
11
14
|
export function curve(points, tension = 1, opts = {}) {
|
|
12
15
|
if (points.length <= 1)
|
|
13
16
|
throw new Error('curve expects at least 2 points');
|
package/src/utils/utils.js
CHANGED
|
@@ -2,19 +2,37 @@ import { curve } from './motionpath.js';
|
|
|
2
2
|
|
|
3
3
|
export { curve };
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Explicitly tells a property to animate the to value
|
|
7
|
+
*/
|
|
5
8
|
export function to(to) {
|
|
6
9
|
return { to };
|
|
7
10
|
}
|
|
8
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Explicitly tells a property to animate the from value
|
|
14
|
+
*/
|
|
9
15
|
export function from(from) {
|
|
10
16
|
return { from };
|
|
11
17
|
}
|
|
12
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Explicitly tells a property to animate with the from and to values
|
|
21
|
+
*/
|
|
13
22
|
export function fromTo(from, to) {
|
|
14
23
|
return { from, to };
|
|
15
24
|
}
|
|
16
25
|
|
|
17
|
-
|
|
26
|
+
/**
|
|
27
|
+
* makes a value reactive to `Timeline::update` calls or resizes
|
|
28
|
+
*/
|
|
29
|
+
export function responsive(fn) {
|
|
30
|
+
return { responsive: fn };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Converts an element with text into span with chars
|
|
35
|
+
*/
|
|
18
36
|
export function chars(element) {
|
|
19
37
|
if (element.dataset.processedChars)
|
|
20
38
|
return Array.from(element.children);
|
|
@@ -34,7 +52,9 @@ export function chars(element) {
|
|
|
34
52
|
});
|
|
35
53
|
}
|
|
36
54
|
|
|
37
|
-
|
|
55
|
+
/**
|
|
56
|
+
* get the offset to the current page page
|
|
57
|
+
*/
|
|
38
58
|
export function pageOffset(el) {
|
|
39
59
|
if ('offsetTop' in el) {
|
|
40
60
|
return {
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { COLORS } from './defaultcolors.js';
|
|
2
|
+
|
|
3
|
+
export default class ColorValue {
|
|
4
|
+
// [r, g, b, a?]
|
|
5
|
+
constructor(v) {
|
|
6
|
+
if (v.length === 3)
|
|
7
|
+
v = [...v, 1];
|
|
8
|
+
|
|
9
|
+
// always [r, g, b, a]
|
|
10
|
+
this.values = v;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
static parse(v) {
|
|
14
|
+
if (Array.isArray(v)) {
|
|
15
|
+
if (v.length < 3 || v.length > 4)
|
|
16
|
+
throw new Error('expected array [r, g, b, a]');
|
|
17
|
+
|
|
18
|
+
return new ColorValue(v);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (typeof v !== 'string')
|
|
22
|
+
throw new Error('expected a string or an array');
|
|
23
|
+
|
|
24
|
+
v = v.trim();
|
|
25
|
+
|
|
26
|
+
if (v.startsWith('#'))
|
|
27
|
+
return new ColorValue(parseHex(v.substring(1)));
|
|
28
|
+
if (v.startsWith('rgb'))
|
|
29
|
+
return new ColorValue(parseRgb(v));
|
|
30
|
+
if (v.startsWith('hsl'))
|
|
31
|
+
return new ColorValue(parseHsl(v));
|
|
32
|
+
|
|
33
|
+
if (v in COLORS)
|
|
34
|
+
return new ColorValue(COLORS[v]);
|
|
35
|
+
|
|
36
|
+
throw new Error('unknown color value ' + v);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// v needs to be a string
|
|
40
|
+
static mightBeAColor(v) {
|
|
41
|
+
v = v.trim();
|
|
42
|
+
|
|
43
|
+
return v.startsWith('#')
|
|
44
|
+
|| v.startsWith('rgb')
|
|
45
|
+
|| v.startsWith('hsl')
|
|
46
|
+
|| v in COLORS;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
clone() {
|
|
50
|
+
return new ColorValue(this.values.slice());
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
toString() {
|
|
54
|
+
const [r, g, b, a] = this.values;
|
|
55
|
+
return `rgba(${[r, g, b].map(v => Math.round(v)).join(', ')}, ${
|
|
56
|
+
a.toFixed(3)
|
|
57
|
+
})`;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// hex without the hash
|
|
62
|
+
function parseHex(hex) {
|
|
63
|
+
if (hex.length !== 3 && hex.length !== 6 && hex.length !== 8)
|
|
64
|
+
throw new Error('unknown hex value ' + hex);
|
|
65
|
+
|
|
66
|
+
// Convert 3-character hex to 6-character hex
|
|
67
|
+
if (hex.length === 3)
|
|
68
|
+
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
|
|
69
|
+
|
|
70
|
+
// Parse the hex values
|
|
71
|
+
const r = parseInt(hex.substring(0, 2), 16);
|
|
72
|
+
const g = parseInt(hex.substring(2, 4), 16);
|
|
73
|
+
const b = parseInt(hex.substring(4, 6), 16);
|
|
74
|
+
let a = 255;
|
|
75
|
+
|
|
76
|
+
if (hex.length === 8)
|
|
77
|
+
a = parseInt(hex.substring(6, 8), 16);
|
|
78
|
+
|
|
79
|
+
return [r, g, b, a / 255];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// rgb needs to start with rgb
|
|
83
|
+
function parseRgb(rgb) {
|
|
84
|
+
const rgba = rgb.startsWith('rgba');
|
|
85
|
+
// remove the function name
|
|
86
|
+
rgb = rgb.substring(3 + rgba);
|
|
87
|
+
if (!rgb.startsWith('(') && !rgb.endsWith(')'))
|
|
88
|
+
throw new Error('invalid rgb function ' + rgb);
|
|
89
|
+
|
|
90
|
+
rgb = rgb.substring(1, rgb.length - 1);
|
|
91
|
+
const vals = rgb.split(',');
|
|
92
|
+
|
|
93
|
+
if ((rgba && vals.length !== 4) || vals.length !== 3)
|
|
94
|
+
throw new Error('invalid rgb function ' + rgb);
|
|
95
|
+
|
|
96
|
+
const r = parseInt(vals[0].trim());
|
|
97
|
+
const g = parseInt(vals[1].trim());
|
|
98
|
+
const b = parseInt(vals[2].trim());
|
|
99
|
+
const a = rgba ? parseFloat(vals[3].trim()) : 1;
|
|
100
|
+
|
|
101
|
+
return [r, g, b, a];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// hsl needs to start with hsl
|
|
105
|
+
function parseHsl(hsl) {
|
|
106
|
+
const hsla = hsl.startsWith('hsla');
|
|
107
|
+
// Remove the function name
|
|
108
|
+
hsl = hsl.substring(3 + hsla);
|
|
109
|
+
if (!hsl.startsWith('(') || !hsl.endsWith(')'))
|
|
110
|
+
throw new Error('invalid hsl function ' + hsl);
|
|
111
|
+
|
|
112
|
+
hsl = hsl.substring(1, hsl.length - 1);
|
|
113
|
+
let vals = hsl.split(',');
|
|
114
|
+
|
|
115
|
+
if ((hsla && vals.length !== 4) || (!hsla && vals.length !== 3))
|
|
116
|
+
throw new Error('invalid hsl function ' + hsl);
|
|
117
|
+
|
|
118
|
+
vals = vals.map(v => v.trim());
|
|
119
|
+
|
|
120
|
+
if (!vals[1].endsWith('%') && !vals[2].endsWith('%'))
|
|
121
|
+
throw new Error('invalid hsl function ' + hsl);
|
|
122
|
+
|
|
123
|
+
const h = parseInt(vals[0]);
|
|
124
|
+
const s = parseInt(vals[1].substring(0, vals[1].length - 1));
|
|
125
|
+
const l = parseInt(vals[2].substring(0, vals[2].length - 1));
|
|
126
|
+
const a = hsla ? parseFloat(vals[3]) : 1;
|
|
127
|
+
|
|
128
|
+
return hslToRgba([h, s, l, a]);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/// expects [h, s, l, a]
|
|
132
|
+
function hslToRgba(hsla) {
|
|
133
|
+
let [h, s, l, a] = hsla;
|
|
134
|
+
|
|
135
|
+
// normalize
|
|
136
|
+
h /= 360;
|
|
137
|
+
s /= 100;
|
|
138
|
+
l /= 100;
|
|
139
|
+
|
|
140
|
+
let r, g, b;
|
|
141
|
+
if (s === 0) {
|
|
142
|
+
r = g = b = l;
|
|
143
|
+
} else {
|
|
144
|
+
const q = l < .5 ? l * (1 + s) : l + s - l * s;
|
|
145
|
+
const p = 2 * l - q;
|
|
146
|
+
r = Math.round(hueToRgb(p, q, h + 1 / 3) * 255, 0);
|
|
147
|
+
g = Math.round(hueToRgb(p, q, h) * 255, 0);
|
|
148
|
+
b = Math.round(hueToRgb(p, q, h - 1 / 3) * 255, 0);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return [r, g, b, a];
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function hueToRgb(p, q, t) {
|
|
155
|
+
if (t < 0)
|
|
156
|
+
t += 1;
|
|
157
|
+
if (t > 1)
|
|
158
|
+
t -= 1;
|
|
159
|
+
|
|
160
|
+
if (t < 1 / 6)
|
|
161
|
+
return p + (q - p) * 6 * t;
|
|
162
|
+
if (t < 1 / 2)
|
|
163
|
+
return q;
|
|
164
|
+
if (t < 2 / 3)
|
|
165
|
+
return p + (q - p) * (2 / 3 - t) * 6;
|
|
166
|
+
return p;
|
|
167
|
+
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
export const COLORS = {
|
|
2
|
+
black: [0, 0, 0],
|
|
3
|
+
silver: [192, 192, 192],
|
|
4
|
+
gray: [128, 128, 128],
|
|
5
|
+
white: [255, 255, 255],
|
|
6
|
+
maroon: [128, 0, 0],
|
|
7
|
+
red: [255, 0, 0],
|
|
8
|
+
purple: [128, 0, 128],
|
|
9
|
+
fuchsia: [255, 0, 255],
|
|
10
|
+
green: [0, 128, 0],
|
|
11
|
+
lime: [0, 255, 0],
|
|
12
|
+
olive: [128, 128, 0],
|
|
13
|
+
yellow: [255, 255, 0],
|
|
14
|
+
navy: [0, 0, 128],
|
|
15
|
+
blue: [0, 0, 255],
|
|
16
|
+
teal: [0, 128, 128],
|
|
17
|
+
aqua: [0, 255, 255],
|
|
18
|
+
aliceblue: [240, 248, 255],
|
|
19
|
+
antiquewhite: [250, 235, 215],
|
|
20
|
+
aquamarine: [127, 255, 212],
|
|
21
|
+
azure: [240, 255, 255],
|
|
22
|
+
beige: [245, 245, 220],
|
|
23
|
+
bisque: [255, 228, 196],
|
|
24
|
+
blanchedalmond: [255, 235, 205],
|
|
25
|
+
blueviolet: [138, 43, 226],
|
|
26
|
+
brown: [165, 42, 42],
|
|
27
|
+
burlywood: [222, 184, 135],
|
|
28
|
+
cadetblue: [95, 158, 160],
|
|
29
|
+
chartreuse: [127, 255, 0],
|
|
30
|
+
chocolate: [210, 105, 30],
|
|
31
|
+
coral: [255, 127, 80],
|
|
32
|
+
cornflowerblue: [100, 149, 237],
|
|
33
|
+
cornsilk: [255, 248, 220],
|
|
34
|
+
crimson: [220, 20, 60],
|
|
35
|
+
cyan: [0, 255, 255],
|
|
36
|
+
darkblue: [0, 0, 139],
|
|
37
|
+
darkcyan: [0, 139, 139],
|
|
38
|
+
darkgoldenrod: [184, 134, 11],
|
|
39
|
+
darkgray: [169, 169, 169],
|
|
40
|
+
darkgreen: [0, 100, 0],
|
|
41
|
+
darkgrey: [169, 169, 169],
|
|
42
|
+
darkkhaki: [189, 183, 107],
|
|
43
|
+
darkmagenta: [139, 0, 139],
|
|
44
|
+
darkolivegreen: [85, 107, 47],
|
|
45
|
+
darkorange: [255, 140, 0],
|
|
46
|
+
darkorchid: [153, 50, 204],
|
|
47
|
+
darkred: [139, 0, 0],
|
|
48
|
+
darksalmon: [233, 150, 122],
|
|
49
|
+
darkseagreen: [143, 188, 143],
|
|
50
|
+
darkslateblue: [72, 61, 139],
|
|
51
|
+
darkslategray: [47, 79, 79],
|
|
52
|
+
darkslategrey: [47, 79, 79],
|
|
53
|
+
darkturquoise: [0, 206, 209],
|
|
54
|
+
darkviolet: [148, 0, 211],
|
|
55
|
+
deeppink: [255, 20, 147],
|
|
56
|
+
deepskyblue: [0, 191, 255],
|
|
57
|
+
dimgray: [105, 105, 105],
|
|
58
|
+
dimgrey: [105, 105, 105],
|
|
59
|
+
dodgerblue: [30, 144, 255],
|
|
60
|
+
firebrick: [178, 34, 34],
|
|
61
|
+
floralwhite: [255, 250, 240],
|
|
62
|
+
forestgreen: [34, 139, 34],
|
|
63
|
+
gainsboro: [220, 220, 220],
|
|
64
|
+
ghostwhite: [248, 248, 255],
|
|
65
|
+
gold: [255, 215, 0],
|
|
66
|
+
goldenrod: [218, 165, 32],
|
|
67
|
+
greenyellow: [173, 255, 47],
|
|
68
|
+
honeydew: [240, 255, 240],
|
|
69
|
+
hotpink: [255, 105, 180],
|
|
70
|
+
indianred: [205, 92, 92],
|
|
71
|
+
indigo: [75, 0, 130],
|
|
72
|
+
ivory: [255, 255, 240],
|
|
73
|
+
khaki: [240, 230, 140],
|
|
74
|
+
lavender: [230, 230, 250],
|
|
75
|
+
lavenderblush: [255, 240, 245],
|
|
76
|
+
lawngreen: [124, 252, 0],
|
|
77
|
+
lemonchiffon: [255, 250, 205],
|
|
78
|
+
lightblue: [173, 216, 230],
|
|
79
|
+
lightcoral: [240, 128, 128],
|
|
80
|
+
lightcyan: [224, 255, 255],
|
|
81
|
+
lightgoldenrodyellow: [250, 250, 210],
|
|
82
|
+
lightgray: [211, 211, 211],
|
|
83
|
+
lightgreen: [144, 238, 144],
|
|
84
|
+
lightgrey: [211, 211, 211],
|
|
85
|
+
lightpink: [255, 182, 193],
|
|
86
|
+
lightsalmon: [255, 160, 122],
|
|
87
|
+
lightseagreen: [32, 178, 170],
|
|
88
|
+
lightskyblue: [135, 206, 250],
|
|
89
|
+
lightslategray: [119, 136, 153],
|
|
90
|
+
lightslategrey: [119, 136, 153],
|
|
91
|
+
lightsteelblue: [176, 196, 222],
|
|
92
|
+
lightyellow: [255, 255, 224],
|
|
93
|
+
limegreen: [50, 205, 50],
|
|
94
|
+
linen: [250, 240, 230],
|
|
95
|
+
magenta: [255, 0, 255],
|
|
96
|
+
mediumaquamarine: [102, 205, 170],
|
|
97
|
+
mediumblue: [0, 0, 205],
|
|
98
|
+
mediumorchid: [186, 85, 211],
|
|
99
|
+
mediumpurple: [147, 112, 219],
|
|
100
|
+
mediumseagreen: [60, 179, 113],
|
|
101
|
+
mediumslateblue: [123, 104, 238],
|
|
102
|
+
mediumspringgreen: [0, 250, 154],
|
|
103
|
+
mediumturquoise: [72, 209, 204],
|
|
104
|
+
mediumvioletred: [199, 21, 133],
|
|
105
|
+
midnightblue: [25, 25, 112],
|
|
106
|
+
mintcream: [245, 255, 250],
|
|
107
|
+
mistyrose: [255, 228, 225],
|
|
108
|
+
moccasin: [255, 228, 181],
|
|
109
|
+
navajowhite: [255, 222, 173],
|
|
110
|
+
oldlace: [253, 245, 230],
|
|
111
|
+
olivedrab: [107, 142, 35],
|
|
112
|
+
orange: [255, 165, 0],
|
|
113
|
+
orangered: [255, 69, 0],
|
|
114
|
+
orchid: [218, 112, 214],
|
|
115
|
+
palegoldenrod: [238, 232, 170],
|
|
116
|
+
palegreen: [152, 251, 152],
|
|
117
|
+
paleturquoise: [175, 238, 238],
|
|
118
|
+
palevioletred: [219, 112, 147],
|
|
119
|
+
papayawhip: [255, 239, 213],
|
|
120
|
+
peachpuff: [255, 218, 185],
|
|
121
|
+
peru: [205, 133, 63],
|
|
122
|
+
pink: [255, 192, 203],
|
|
123
|
+
plum: [221, 160, 221],
|
|
124
|
+
powderblue: [176, 224, 230],
|
|
125
|
+
rosybrown: [188, 143, 143],
|
|
126
|
+
royalblue: [65, 105, 225],
|
|
127
|
+
saddlebrown: [139, 69, 19],
|
|
128
|
+
salmon: [250, 128, 114],
|
|
129
|
+
sandybrown: [244, 164, 96],
|
|
130
|
+
seagreen: [46, 139, 87],
|
|
131
|
+
seashell: [255, 245, 238],
|
|
132
|
+
sienna: [160, 82, 45],
|
|
133
|
+
skyblue: [135, 206, 235],
|
|
134
|
+
slateblue: [106, 90, 205],
|
|
135
|
+
slategray: [112, 128, 144],
|
|
136
|
+
slategrey: [112, 128, 144],
|
|
137
|
+
snow: [255, 250, 250],
|
|
138
|
+
springgreen: [0, 255, 127],
|
|
139
|
+
steelblue: [70, 130, 180],
|
|
140
|
+
tan: [210, 180, 140],
|
|
141
|
+
thistle: [216, 191, 216],
|
|
142
|
+
tomato: [255, 99, 71],
|
|
143
|
+
turquoise: [64, 224, 208],
|
|
144
|
+
violet: [238, 130, 238],
|
|
145
|
+
wheat: [245, 222, 179],
|
|
146
|
+
whitesmoke: [245, 245, 245],
|
|
147
|
+
yellowgreen: [154, 205, 50]
|
|
148
|
+
};
|