aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuben Beltran del Rio <ruben@unlimited.pizza>2023-07-20 21:14:07 +0200
committerRuben Beltran del Rio <ruben@unlimited.pizza>2023-07-20 21:14:07 +0200
commit3ec245a003e4e0cdecc9d58c1cac8b1b0f081fb4 (patch)
tree16268ddf5c517f16c76680198aac45dffe1cf845
parenta6a71e448b7f88bbf2d00e23a53355777373d3fb (diff)
Add the pattern selector
-rw-r--r--css/application.css48
-rw-r--r--index.html14
-rw-r--r--js/fyr.js112
-rw-r--r--js/updater.js36
4 files changed, 165 insertions, 45 deletions
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 @@
<link rel="icon" type="image/png" sizes="96x96" href="/images/icon96.png">
<link rel="icon" type="image/png" sizes="16x16" href="/images/icon16.png">
- <script type="module" src="/js/updater.js"></script>
+ <script type="module" src="/js/fyr.js"></script>
</head>
<body>
<div class="content-wrapper">
@@ -23,7 +23,17 @@
<h1><img alt="" src="/images/logo.png" />Fyr.</h1>
<p>Communicate through light.</p>
<h2>Update Status</h2>
- <div class="updater" />
+ <p>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.</p>
+ <div class="timeline"></div>
+ <div class="color-editor">
+ <div class="color"></div>
+ <div class="light"></div>
+ <p class="x-label">Hue →</p>
+ <p class="z-label">Lightness ⇈</p>
+ <p class="y-label">Saturation →</p>
+ </div>
+ <button class="post">Post</button>
+ <button class="clear">Clear</button>
</main>
</div>
</body>
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);
-});