Skip to content

Commit 035a3b5

Browse files
LeaVeroufantasai
andcommitted
[css-color-4] Playground for hue interpolation algorithms
Co-Authored-By: fantasai <725717+fantasai@users.noreply.github.com>
1 parent 0faad0a commit 035a3b5

File tree

3 files changed

+129
-0
lines changed

3 files changed

+129
-0
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
5+
<meta charset="UTF-8">
6+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
7+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
8+
<title>Hue interpolation playground</title>
9+
<link rel="stylesheet" href="style.css">
10+
11+
</head>
12+
<body>
13+
14+
<fieldset>
15+
<legend>Algorithm</legend>
16+
17+
<label>
18+
<input type="radio" name="algorithm" value="current-spec">
19+
Current spec
20+
</label>
21+
22+
<label>
23+
<input type="radio" name="algorithm" value="new" checked>
24+
New
25+
</label>
26+
</fieldset>
27+
28+
<div id="inputs">
29+
<label>
30+
θ<sub>1</sub> = <input type="number" id="theta1" value="360" step="1">deg
31+
</label>
32+
<label>
33+
θ<sub>2</sub> = <input type="number" id="theta2" value="720" step="1">deg
34+
</label>
35+
</div>
36+
37+
<output id="output">
38+
<p>Normalized angles:</p>
39+
<p>
40+
θ<sub>1</sub> = <span id="theta1n"></span>deg
41+
θ<sub>2</sub> = <span id="theta2n"></span>deg
42+
</p>
43+
<div id="gradient"></div>
44+
</output>
45+
46+
<script src="index.js" type="module"></script>
47+
48+
</body>
49+
</html>
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
(document.body.oninput = evt => {
2+
3+
let θ1 = +theta1.value;
4+
let θ2 = +theta2.value;
5+
6+
let range = normalizeAngleRange(θ1, θ2);
7+
8+
theta1n.textContent = range[0];
9+
theta2n.textContent = range[1];
10+
11+
let colors = interpolate(range[0], range[1], 10).map(θ => `hsl(${θ}, 100%, 50%)`);
12+
gradient.style.background = `linear-gradient(to right, ${colors.join(", ")})`;
13+
14+
})();
15+
16+
function normalizeAngle (θ) {
17+
return (θ % 360 + 360) % 360;
18+
}
19+
20+
function normalizeAngleRange(θ1, θ2) {
21+
let algorithm = document.querySelector("input[name=algorithm]:checked").value;
22+
23+
if (algorithm === "current-spec") {
24+
θ1 = normalizeAngle(θ1);
25+
θ2 = normalizeAngle(θ2);
26+
}
27+
else {
28+
let θmax = Math.max(θ1, θ2);
29+
let θmin = Math.min(θ1, θ2);
30+
let Δ = θmax - θmin;
31+
32+
// Min common number of turns
33+
let T = Math.floor(θmin / 360);
34+
35+
// Cap Δ at 360
36+
if (Δ > 360) {
37+
Δ = Δ % 360;
38+
if (Δ === 0) {
39+
Δ = 360;
40+
}
41+
}
42+
if (θmax === θ1) {
43+
θ1 = θ2 + Δ;
44+
}
45+
else {
46+
θ2 = θ1 + Δ;
47+
}
48+
49+
// Subtract min common number of turns from both
50+
θ1 -= T * 360;
51+
θ2 -= T * 360;
52+
}
53+
54+
return [θ1, θ2];
55+
}
56+
57+
function interpolate (start, end, steps) {
58+
let ret = [];
59+
let step = (end - start) / steps;
60+
for (let i = 0; i < steps; i++) {
61+
ret.push(start + step * i);
62+
}
63+
return ret;
64+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
body {
2+
font: 150%/1.5 system-ui;
3+
}
4+
5+
input {
6+
font: inherit;
7+
}
8+
9+
#inputs {
10+
display: flex;
11+
gap: .5em;
12+
}
13+
14+
#gradient {
15+
height: 20px;
16+
}

0 commit comments

Comments
 (0)