diff options
| author | Ruben Beltran del Rio <ruben@unlimited.pizza> | 2023-07-20 21:14:07 +0200 |
|---|---|---|
| committer | Ruben Beltran del Rio <ruben@unlimited.pizza> | 2023-07-20 21:14:07 +0200 |
| commit | 3ec245a003e4e0cdecc9d58c1cac8b1b0f081fb4 (patch) | |
| tree | 16268ddf5c517f16c76680198aac45dffe1cf845 /js/fyr.js | |
| parent | a6a71e448b7f88bbf2d00e23a53355777373d3fb (diff) | |
Add the pattern selector
Diffstat (limited to 'js/fyr.js')
| -rw-r--r-- | js/fyr.js | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/js/fyr.js b/js/fyr.js new file mode 100644 index 0000000..e6c727c --- /dev/null +++ b/js/fyr.js @@ -0,0 +1,112 @@ +var color = document.querySelector('.color'), + light = document.querySelector('.light'), + timeline = document.querySelector('.timeline'), + clear = document.querySelector('.clear'), + colors = [], + selecting = false, + recording = false, + animationTime = 0, + lastFrame = 0, + t = null, + h = 0, + s = 100, + l = 50; + +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}%) ${Math.round(100*last/3000)}%,`; + background += `hsl(${h} ${s}% ${l}%) ${Math.round(100*(last+now)/3000)}%,`; + last += now; + } + background += `black ${Math.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 = Math.min(3000, Date.now() - t); + addColor(); + c = colors[colors.length - 1]; + } + if (l >= 3000) return; + c.t = Math.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 = Math.round(360 * x / 200); + s = Math.round(100 * (200 - y) / 200); + render(); +}); + +color.addEventListener('wheel', ({deltaY: y}) => { + selecting = true; + l = Math.min(Math.max(0, l + y/4), 100) + render(); +}); + +color.addEventListener('mousedown', () => { + addColor(); + recording = true; + setTimeout(record, 100); +}); + +color.addEventListener('mouseup', () => { + recording = false; +}); + +color.addEventListener('mouseenter', () => { + selecting = true; +}); + +color.addEventListener('mouseout', () => { + recording = false; + selecting = false; + window.requestAnimationFrame(preview); +}); + +clear.addEventListener('click', () => { + colors = []; + renderTimeline(); +}); + +render(); +renderTimeline(); |