worker orbs: drive the render loop with setInterval on firefox (permanent 1fps fix)
the dashboard orb canvas kept falling back to ~1fps on firefox after the page settled. root cause: firefox throttles requestAnimationFrame to ~1fps for a canvas it heuristically deems occluded. the WAA keepalive only delayed the heuristic; it re-fired over time. real fix: on firefox, drive tick() with a setInterval(~60fps) instead of self-scheduling rAF — setInterval is not subject to the canvas-occlusion rAF throttle, so the orbs stay at full framerate indefinitely. chrome is untouched (keeps vsync-aligned rAF). same render workload (idle still drops to 20fps via the existing sleep skip); background tabs still parked by the visibilitychange handler → stopLoop clears the interval. kept the keepalive (harmless).
This commit is contained in:
parent
80d84c6de3
commit
88b68b8073
1 changed files with 21 additions and 1 deletions
|
|
@ -68,6 +68,13 @@
|
|||
let errorHeat = 0; // 0..1 aggregate "stress" — bumps on real worker errors, decays over time
|
||||
let state = 'idle';
|
||||
let animFrame = null;
|
||||
let intervalId = null;
|
||||
// Firefox throttles requestAnimationFrame to ~1fps for a canvas it heuristically deems
|
||||
// occluded — the dashboard orb canvas falls into this after the page settles (the keepalive
|
||||
// only delays it). A setInterval-driven loop is NOT subject to that canvas-occlusion rAF
|
||||
// throttle, so on Firefox we drive the render with a timer. Chrome keeps rAF untouched
|
||||
// (works fine + vsync-aligned). Background tabs are still parked via onVisibility→stopLoop.
|
||||
const _isFirefox = !!(window.CSS && CSS.supports && CSS.supports('-moz-appearance', 'none'));
|
||||
let onDashboard = false;
|
||||
let expandProgress = 0;
|
||||
let staggerTimers = [];
|
||||
|
|
@ -566,6 +573,12 @@
|
|||
})();
|
||||
|
||||
function startLoop() {
|
||||
if (_isFirefox) {
|
||||
if (intervalId) return;
|
||||
// ~60fps timer — immune to Firefox's canvas-occlusion rAF throttle.
|
||||
intervalId = setInterval(tick, 1000 / 60);
|
||||
return;
|
||||
}
|
||||
if (animFrame) return;
|
||||
tick();
|
||||
}
|
||||
|
|
@ -575,10 +588,17 @@
|
|||
cancelAnimationFrame(animFrame);
|
||||
animFrame = null;
|
||||
}
|
||||
if (intervalId) {
|
||||
clearInterval(intervalId);
|
||||
intervalId = null;
|
||||
}
|
||||
}
|
||||
|
||||
function tick() {
|
||||
animFrame = requestAnimationFrame(tick);
|
||||
// Chrome self-schedules via rAF; Firefox is driven by the setInterval above.
|
||||
if (!_isFirefox) {
|
||||
animFrame = requestAnimationFrame(tick);
|
||||
}
|
||||
if (!canvas || !ctx) return;
|
||||
|
||||
// Yield the frame to active scrolling (orbs freeze, resume on idle).
|
||||
|
|
|
|||
Loading…
Reference in a new issue