Fix bug where changing tabs would *always* pause the outfit animations

We have a feature to check the movie's FPS, and pause it if it gets too
low, as a guard against especially low-performance movies. But this was
triggering in an *expected* case, where browsers intentionally throttle
interval events when a page is in the background (e.g. you switch to
another tab).

Now, our rendering is aware of page visibility: when the page is
hidden, don't bother rendering, and keep resetting the FPS counter
state, so that we can pick up with a fresh FPS counter when the page
comes back.
This commit is contained in:
Emi Matchu 2024-06-12 17:05:53 -07:00
parent cedceeaf3c
commit 60e9130891

View file

@ -196,26 +196,37 @@ function OutfitMovieLayer({
let lastFpsLoggedAtInMs = performance.now(); let lastFpsLoggedAtInMs = performance.now();
let numFramesSinceLastLogged = 0; let numFramesSinceLastLogged = 0;
const intervalId = setInterval(() => { const intervalId = setInterval(() => {
updateStage();
numFramesSinceLastLogged++;
const now = performance.now(); const now = performance.now();
const timeSinceLastFpsLoggedAtInMs = now - lastFpsLoggedAtInMs; const timeSinceLastFpsLoggedAtInMs = now - lastFpsLoggedAtInMs;
const timeSinceLastFpsLoggedAtInSec = timeSinceLastFpsLoggedAtInMs / 1000; const timeSinceLastFpsLoggedAtInSec = timeSinceLastFpsLoggedAtInMs / 1000;
if (timeSinceLastFpsLoggedAtInSec > 2) {
const fps = numFramesSinceLastLogged / timeSinceLastFpsLoggedAtInSec; const fps = numFramesSinceLastLogged / timeSinceLastFpsLoggedAtInSec;
const roundedFps = Math.round(fps * 100) / 100; const roundedFps = Math.round(fps * 100) / 100;
// If the page is visible, render the next frame, and track that we did.
// And if it's been 2 seconds since the last time we logged the FPS,
// compute and log the FPS during those two seconds. (Checking the page
// visibility is both an optimization to avoid rendering the movie, but
// also makes "low FPS" tracking more accurate: browsers already throttle
// intervals when the page is hidden, so a low FPS is *expected*, and
// wouldn't indicate a performance problem like a low FPS normally would.)
if (!document.hidden) {
updateStage();
numFramesSinceLastLogged++;
if (timeSinceLastFpsLoggedAtInSec > 2) {
console.debug( console.debug(
`[OutfitMovieLayer] FPS: ${roundedFps} (Target: ${targetFps}) (${libraryUrl})`, `[OutfitMovieLayer] FPS: ${roundedFps} (Target: ${targetFps}) (${libraryUrl})`,
); );
if (onLowFps && fps < 2) { if (onLowFps && fps < 2) {
onLowFps(fps); onLowFps(fps);
} }
lastFpsLoggedAtInMs = now;
numFramesSinceLastLogged = 0;
}
} else {
// Otherwise, if the page is hidden, keep resetting the FPS tracker
// state, to be able to pick up counting fresh once we come back.
lastFpsLoggedAtInMs = now; lastFpsLoggedAtInMs = now;
numFramesSinceLastLogged = 0; numFramesSinceLastLogged = 0;
} }