Dashboard worker orbs bloom from center instead of creeping in from top-left

On page load every orb sat at the canvas origin: orbs are created at (0,0) and
the random scatter skipped orbs that weren't visible yet — which on load is all
of them, since the header hasn't been laid out when init() runs. The whole
cluster then drifted in from the top-left corner.

scatterOrbs() -> centerOrbs(): spawn the cluster dead-center of the canvas,
positioning every orb regardless of visibility (a few px of jitter on purpose —
the separation force ignores pairs closer than 0.1px, so a perfect stack would
never split). enterOrbState() also re-centers right after resizeCanvas(), so
activations get the true center even when init ran against a hidden 0x0 header
— and returning to the dashboard replays the center-bloom intro.
This commit is contained in:
BoulderBadgeDad 2026-06-06 14:30:54 -07:00
parent fe1366d9e0
commit ee13bc8a05

View file

@ -117,7 +117,7 @@
});
computeHomes();
scatterOrbs();
centerOrbs();
dashboardHeader.addEventListener('mouseenter', onMouseEnter);
dashboardHeader.addEventListener('mouseleave', onMouseLeave);
@ -137,15 +137,22 @@
});
}
function scatterOrbs() {
function centerOrbs() {
// Spawn the whole cluster dead-center and let the physics bloom it
// outward. Positions EVERY orb (visible or not): the old random
// scatter skipped not-yet-visible orbs, so on page load they all sat
// at the canvas origin and drifted in from the top-left corner.
if (!canvas) return;
const w = canvas.clientWidth || 600;
const h = canvas.clientHeight || 80;
orbs.forEach(orb => {
if (!orb.visible) return;
orb.x = ORB_RADIUS + Math.random() * (w - ORB_DIAMETER);
orb.y = ORB_RADIUS + Math.random() * (h - ORB_DIAMETER);
// A few px of jitter so the separation force can split the stack
// (it ignores pairs closer than 0.1px).
orb.x = w / 2 + (Math.random() - 0.5) * 6;
orb.y = h / 2 + (Math.random() - 0.5) * 6;
orb.vx = (Math.random() - 0.5) * 0.6;
orb.vy = (Math.random() - 0.5) * 0.6;
});
}
@ -322,6 +329,10 @@
canvas.style.opacity = '1';
canvas.style.display = '';
resizeCanvas();
// Dashboard (re)activation: the canvas just got its real size — init may
// have run while the header was hidden (0x0), leaving positions stale.
// Bloom the cluster from dead center instead of wherever that left them.
centerOrbs();
startLoop();
}