It's a proper clock! The hands fill up to one end, then empty, then it all starts again.

The period is 60 seconds for the small hand, and 60 minutes for the big hand, so it matches a standard clock.
This commit is contained in:
Christian Lawson-Perfect 2025-03-17 09:51:42 +00:00
parent 6ddcc2f893
commit 2c7badf010
2 changed files with 23 additions and 17 deletions

View file

@ -9,17 +9,17 @@
</head> </head>
<body> <body>
<main> <main>
<svg id="board" viewBox="-0.3 -0.3 1.6 1.6"> <svg id="board" viewBox="-0.3 -0.3 1.6 1.6" style="max-height: 100svh">
<defs> <defs>
<linearGradient id="dots-gradient"> <linearGradient id="dots-gradient">
<stop offset="0%" stop-color="green" /> <stop offset="0%" stop-color="green" />
<stop offset="100%" stop-color="white" /> <stop offset="100%" stop-color="white" />
</linearGradient> </linearGradient>
</defs> </defs>
<rect x="-100" y="-100" width="200" height="200" fill="hsl(120,30%,50%)"/> <rect x="-100" y="-100" width="200" height="200" fill="hsl(140,60%,60%)"/>
<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(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"/> <path class="curve" fill="none" stroke="hsl(240,50%,50%)" stroke-width="0.01" stroke-linejoin="round" stroke-linecap="square"/>
<path id="dots" fill="none" stroke="hsl(240,20%,90%)" stroke-width="0.01" stroke-linejoin="round" stroke-linecap="round"/>
<text id="debug" fill="white" font-size="0.1"></debug> <text id="debug" fill="white" font-size="0.1"></debug>
</svg> </svg>
</main> </main>

View file

@ -7,6 +7,8 @@ const rules = {
"B": "-AF+BFB+FA-", "B": "-AF+BFB+FA-",
}; };
steps = Math.min(steps,5); // make sure I don't type a huge number that crashes my PC
let s = "A"; let s = "A";
for(let i=0;i<steps;i++) { for(let i=0;i<steps;i++) {
let ns = ""; let ns = "";
@ -52,7 +54,7 @@ for(let curve of curves) {
curve.setAttribute('stroke-dasharray',`${length} ${length}`); curve.setAttribute('stroke-dasharray',`${length} ${length}`);
curve.setAttribute('d',d); curve.setAttribute('d',d);
} }
document.getElementById('dots').setAttribute('stroke-width',width*0.4); document.getElementById('dots').setAttribute('stroke-width',width*0.3);
document.getElementById('dots').setAttribute('d',d); document.getElementById('dots').setAttribute('d',d);
document.getElementById('dots').setAttribute('stroke-dasharray',`0 ${m}`); document.getElementById('dots').setAttribute('stroke-dasharray',`0 ${m}`);
@ -65,21 +67,25 @@ function easeLinear(t) {
} }
function frame() { function frame() {
const period = 1000; const segments = 2**(2*steps)-1; // number of segments in the curve
const pips = 2**(2*steps)-1; const period = 1000*60/segments; // One period of the small hand is 60 seconds
let scale = 1; let scale = segments**(curves.length-1);
curves.forEach((curve,i) => { curves.forEach((curve,i) => {
const dt = (new Date() - 0) / scale / period; const now = new Date();
const m = dt % (pips); const midnight = new Date(now.getFullYear(),now.getMonth(),now.getDate());
const t = dt; const dt = (new Date() - midnight) / scale / period;
const l = (Math.floor(m) + easeInOutSine(m % 1))*length/pips; const m = dt % (2*segments);
const n = Math.max(0,easeInOutSine(t))*l; const t = i == 0 ? m : (Math.floor(m) + easeInOutSine(m % 1)); // linear for big hand, eased for small hand
//document.getElementById('debug').textContent = `${m.toFixed(4)} ${length} ${pips}` const a = t/segments; // between 0 and 2
curve.setAttribute('stroke-dasharray',`${l-n} ${length}`); const b = 2*(1-Math.abs(1-a/2));
curve.setAttribute('stroke-dashoffset',-n); const end = Math.min(b,1)*length;
curve.setAttribute('stroke-width',width*(easeInOutSine(t)*0.1+0.9)/2**(i+1)); const start = Math.max(0,b-1)*length;
//document.getElementById('debug').textContent = `${m.toFixed(4)} ${length} ${segments}`
curve.setAttribute('stroke-dasharray',`${end-start} ${2*length}`);
curve.setAttribute('stroke-dashoffset',-start);
curve.setAttribute('stroke-width',width/2**(i));
scale *= pips; scale /= segments;
}) })
requestAnimationFrame(frame); requestAnimationFrame(frame);