first commit. The hands pulse back and forth.
This commit is contained in:
commit
6ddcc2f893
4 changed files with 119 additions and 0 deletions
0
.make.lock
Normal file
0
.make.lock
Normal file
27
index.html
Normal file
27
index.html
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width">
|
||||||
|
<title>A thing made by CLP</title>
|
||||||
|
<script type="module" src="script.js"></script>
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<main>
|
||||||
|
<svg id="board" viewBox="-0.3 -0.3 1.6 1.6">
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="dots-gradient">
|
||||||
|
<stop offset="0%" stop-color="green" />
|
||||||
|
<stop offset="100%" stop-color="white" />
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<rect x="-100" y="-100" width="200" height="200" fill="hsl(120,30%,50%)"/>
|
||||||
|
<path id="dots" fill="none" stroke="hsl(240,20%,80%)" stroke-width="0.01" stroke-linejoin="round" stroke-linecap="round"/>
|
||||||
|
<path class="curve" fill="none" stroke="hsl(24,50%,10%)" stroke-width="0.01" stroke-linejoin="round" stroke-linecap="square"/>
|
||||||
|
<path class="curve" fill="none" stroke="hsl(240,50%,50%)" stroke-width="0.01" stroke-linejoin="round" stroke-linecap="square"/>
|
||||||
|
<text id="debug" fill="white" font-size="0.1"></debug>
|
||||||
|
</svg>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
87
script.js
Normal file
87
script.js
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
let steps = 3;
|
||||||
|
|
||||||
|
console.clear();
|
||||||
|
|
||||||
|
const rules = {
|
||||||
|
"A": "+BF-AFA-FB+",
|
||||||
|
"B": "-AF+BFB+FA-",
|
||||||
|
};
|
||||||
|
|
||||||
|
let s = "A";
|
||||||
|
for(let i=0;i<steps;i++) {
|
||||||
|
let ns = "";
|
||||||
|
for(let c of s) {
|
||||||
|
ns += rules[c] || c;
|
||||||
|
}
|
||||||
|
s = ns;
|
||||||
|
}
|
||||||
|
|
||||||
|
let [x,y] = [0,0];
|
||||||
|
const m = 1/(2**steps-1);
|
||||||
|
let dir = [m,0];
|
||||||
|
let d = 'M 0 0 ';
|
||||||
|
const width = 1.5 * 2**-(steps+1);
|
||||||
|
|
||||||
|
const dots = [];
|
||||||
|
|
||||||
|
for(let c of s) {
|
||||||
|
const [dx,dy] = dir;
|
||||||
|
switch(c) {
|
||||||
|
case '+':
|
||||||
|
dir = [-dy,dx];
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
dir = [dy,-dx];
|
||||||
|
break;
|
||||||
|
case 'F':
|
||||||
|
x += dx;
|
||||||
|
y += dy;
|
||||||
|
d += `l ${dx} ${dy}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
d += 'l 0.000000001 0.000001'; // make sure the final dot is drawn
|
||||||
|
|
||||||
|
const length = (2**(2*steps)-1) * m;
|
||||||
|
|
||||||
|
const curves = Array.from(document.querySelectorAll('.curve'));
|
||||||
|
|
||||||
|
for(let curve of curves) {
|
||||||
|
curve.setAttribute('stroke-width',width);
|
||||||
|
curve.setAttribute('stroke-linecap','round');
|
||||||
|
curve.setAttribute('stroke-dasharray',`${length} ${length}`);
|
||||||
|
curve.setAttribute('d',d);
|
||||||
|
}
|
||||||
|
document.getElementById('dots').setAttribute('stroke-width',width*0.4);
|
||||||
|
document.getElementById('dots').setAttribute('d',d);
|
||||||
|
document.getElementById('dots').setAttribute('stroke-dasharray',`0 ${m}`);
|
||||||
|
|
||||||
|
function easeInOutSine(x) {
|
||||||
|
return -(Math.cos(Math.PI * x) - 1) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
function easeLinear(t) {
|
||||||
|
return 1-2*Math.abs(t % 1 - 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
function frame() {
|
||||||
|
const period = 1000;
|
||||||
|
const pips = 2**(2*steps)-1;
|
||||||
|
let scale = 1;
|
||||||
|
curves.forEach((curve,i) => {
|
||||||
|
const dt = (new Date() - 0) / scale / period;
|
||||||
|
const m = dt % (pips);
|
||||||
|
const t = dt;
|
||||||
|
const l = (Math.floor(m) + easeInOutSine(m % 1))*length/pips;
|
||||||
|
const n = Math.max(0,easeInOutSine(t))*l;
|
||||||
|
//document.getElementById('debug').textContent = `${m.toFixed(4)} ${length} ${pips}`
|
||||||
|
curve.setAttribute('stroke-dasharray',`${l-n} ${length}`);
|
||||||
|
curve.setAttribute('stroke-dashoffset',-n);
|
||||||
|
curve.setAttribute('stroke-width',width*(easeInOutSine(t)*0.1+0.9)/2**(i+1));
|
||||||
|
|
||||||
|
scale *= pips;
|
||||||
|
})
|
||||||
|
|
||||||
|
requestAnimationFrame(frame);
|
||||||
|
}
|
||||||
|
frame();
|
5
style.css
Normal file
5
style.css
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
:root {
|
||||||
|
--spacing: 1em;
|
||||||
|
|
||||||
|
color-scheme: light dark;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue