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
|
var color = document.querySelector('.color'),
light = document.querySelector('.light'),
timeline = document.querySelector('.timeline'),
clear = document.querySelector('.clear'),
colors = [],
selecting = 0,
recording = 0,
animationTime = 0,
lastFrame = 0,
t = null,
h = 0,
s = 100,
l = 50,
{round, min, max} = Math;
function render() {
color.style.backgroundColor = `hsl(${h} ${s}% ${l}%)`;
light.style.transform = `translateY(-${l*2.2}px)`;
}
function renderTimeline() {
var background = 'linear-gradient(90deg,',
last = 0;
for (var {h, s, l, t: now} of colors) {
background += `hsl(${h} ${s}% ${l}%) ${round(100*last/3000)}%,`;
background += `hsl(${h} ${s}% ${l}%) ${round(100*(last+now)/3000)}%,`;
last += now;
}
background += `black ${round(100*last/3000)}%, black 101%)`;
timeline.style.background = background;
}
function length() {
return colors.map((c) => c.t).reduce((s, t) => s + t, 0);
}
function addColor() {
t = Date.now();
colors.push({h, s, l, t: 0});
}
function record() {
if (recording) setTimeout(record, 100);
var c = colors[colors.length - 1],
l = length();
if (c.h !== h || c.s !== s || c.l !== l) {
c.t = min(3000, Date.now() - t);
addColor();
c = colors[colors.length - 1];
}
if (l >= 3000) return;
c.t = min(3000, Date.now() - t);
renderTimeline();
}
function preview(current) {
if (selecting || recording) return;
window.requestAnimationFrame(preview);
var dt = current - lastFrame,
last = 0;
if (dt > 32) {
animationTime = (animationTime + dt) % 3000
color.style.background = `hsl(0 0% 0%)`;
for (var {h, s, l, t: now} of colors) {
if (animationTime >= last && animationTime < last+now) {
color.style.background = `hsl(${h} ${s}% ${l}%)`;
break;
}
last += now;
}
lastFrame = current;
}
}
color.addEventListener('mousemove', ({offsetX: x, offsetY: y}) => {
h = round(360 * x / 200);
s = round(100 * (200 - y) / 200);
render();
});
color.addEventListener('wheel', ({deltaY: y}) => {
selecting = 1;
l = min(max(0, l + y/4), 100)
render();
});
color.addEventListener('mousedown', () => {
addColor();
recording = 1;
setTimeout(record, 100);
});
color.addEventListener('mouseup', () => {
recording = 0;
});
color.addEventListener('mouseenter', () => {
selecting = 1;
});
color.addEventListener('mouseout', () => {
recording = 0;
selecting = 0;
window.requestAnimationFrame(preview);
});
clear.addEventListener('click', () => {
colors = [];
renderTimeline();
});
render();
renderTimeline();
|