98 lines
No EOL
2.4 KiB
JavaScript
98 lines
No EOL
2.4 KiB
JavaScript
let steps = 3;
|
|
|
|
console.clear();
|
|
|
|
const rules = {
|
|
"A": "+BF-AFA-FB+",
|
|
"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";
|
|
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 = [];
|
|
|
|
let i = 0;
|
|
for(let c of s) {
|
|
const [dx,dy] = dir;
|
|
switch(c) {
|
|
case '+':
|
|
dir = [-dy,dx];
|
|
break;
|
|
case '-':
|
|
dir = [dy,-dx];
|
|
break;
|
|
case 'F':
|
|
i += 1;
|
|
x += dx;
|
|
y += dy;
|
|
d += `l ${dx} ${dy}`;
|
|
}
|
|
if(i==61) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
d += 'l 0.000000001 0.000001'; // make sure the final dot is drawn
|
|
|
|
const length = 60 * 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.3);
|
|
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 now = new Date();
|
|
const midnight = new Date(now.getFullYear(),now.getMonth(),now.getDate());
|
|
|
|
const dt = (new Date() - midnight);
|
|
document.body.style.setProperty('--bg-hue',dt*360/(1000*60*60*24));
|
|
|
|
const segments = 60; // number of segments in the curve
|
|
const period = 1000; // One period of the small hand is 60 seconds
|
|
curves.forEach((curve,i) => {
|
|
const m = (dt / period / (60**(1-i))) % (2*60); // between 0 and 120
|
|
//const m = document.getElementById('t').valueAsNumber * 120;
|
|
const t = i == 0 ? m : (Math.floor(m) + easeInOutSine(m % 1)); // linear for big hand, eased for small hand
|
|
const a = t/segments; // between 0 and 2
|
|
const b = 2*(1-Math.abs(1-a/2));
|
|
const end = Math.min(b,1)*length;
|
|
const start = Math.max(0,b-1)*length;
|
|
curve.setAttribute('stroke-dasharray',`${end-start} ${2*length}`);
|
|
curve.setAttribute('stroke-dashoffset',-start);
|
|
curve.setAttribute('stroke-width',width/2**(i));
|
|
})
|
|
|
|
requestAnimationFrame(frame);
|
|
}
|
|
frame(); |