From: Ruben Beltran del Rio Date: Thu, 20 Jul 2023 19:14:07 +0000 (+0200) Subject: Add the pattern selector X-Git-Url: https://git.r.bdr.sh/rbdr/fyr/commitdiff_plain/3ec245a003e4e0cdecc9d58c1cac8b1b0f081fb4?ds=inline Add the pattern selector --- diff --git a/css/application.css b/css/application.css index 10333c3..66d0544 100644 --- a/css/application.css +++ b/css/application.css @@ -18,11 +18,50 @@ a { color: #4F8FE6; } -.updater { +.color-editor { + position: relative; + height: 230px; +} + +.color { width: 200px; height: 200px; background: #fff; - border: 10px solid #0F261F; + margin-left: 20px; +} + +.light { + width: 20px; + height: 20px; + background: #FA2B00; + position: absolute; + left: 220px; +} + +.x-label, .y-label, .z-label { + margin: 0; + padding: 0; + color: #FA2B00; + width: 100px; + position: absolute; + top: 200px; +} + +.y-label { + transform: rotate(-90deg); + left: -45px; + top: 135px; +} + +.z-label { + left: 125px; +} + +.timeline { + width: 200px; + height: 50px; + background: black; + margin: 0 0 0 20px; } @media (prefers-color-scheme: dark) { @@ -30,9 +69,4 @@ a { color: #fff; background: #0F261F; } - - .updater { - background: #0F261F; - border: 10px solid #fff; - } } diff --git a/index.html b/index.html index e503143..257cfe4 100644 --- a/index.html +++ b/index.html @@ -15,7 +15,7 @@ - +
@@ -23,7 +23,17 @@

Fyr.

Communicate through light.

Update Status

-
+

Move your mouse around the color box to change hue and saturation. Scroll inside the box to adjust lightness. Press to start recording the color in the timeline, release to stop.

+
+
+
+
+

Hue →

+

Lightness ⇈

+

Saturation →

+
+ +
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(); diff --git a/js/updater.js b/js/updater.js deleted file mode 100644 index 91c447e..0000000 --- a/js/updater.js +++ /dev/null @@ -1,36 +0,0 @@ -function getColors({x, y}, [{x: ax, y: ay}, {x: bx, y: by}, {x: cx, y: cy}]) { - - if (x < 50 && y < 50) return {r: 255, g: 255, b: 255}; - if (x > 150 && y < 50) return {r: 0, g: 0, b: 0}; - - var { abs, round, min } = Math, - area = abs((bx - ax) * (cy - ay) - (cx - ax) * (by - ay)), - R = abs((bx - x) * (cy - y) - (cx - x) * (by - y)), - G = abs((ax - x) * (cy - y) - (cx - x) * (ay - y)), - B = abs((ax - x) * (by - y) - (bx - x) * (ay - y)); - - // Normalize the areas to get the weights - const weights = { - r: round(255 * min(1, R / area)), - g: round(255 * min(1, G / area)), - b: round(255 * min(1, B / area)) - }; - - return weights; -} - -var updater = document.querySelector('.updater'), - color = {r: 0, g: 0, b: 0}; -updater.addEventListener('mousemove', ({offsetX: x, offsetY: y}) => { - var {r, g, b} = color = getColors( - {x, y}, - [{x: 0, y: 200}, {x: 200, y: 200}, {x: 100, y: 0}] - ) - updater.style.backgroundColor = `rgb(${r}, ${g}, ${b})`; -}); -updater.addEventListener('mousedown', () => { - console.log('Adding Color', color); -}); -updater.addEventListener('mouseup', () => { - console.log('Stop Adding Color', color); -});