optimize rAF calls

This commit is contained in:
“chrisshank” 2024-12-10 13:05:00 -08:00
parent 059441e13c
commit 619fae1ee2
2 changed files with 34 additions and 5 deletions

View File

@ -1,4 +1,5 @@
import { ReactiveController, ReactiveControllerHost } from '@lit/reactive-element';
import { requestAnimationFrame, cancelAnimationFrame } from './rAF';
export interface AnimationFrameControllerHost extends ReactiveControllerHost {
tick(): void;
@ -7,7 +8,6 @@ export interface AnimationFrameControllerHost extends ReactiveControllerHost {
export class AnimationFrameController implements ReactiveController {
#host;
#rAFId = -1;
#lastTime = 0;
#dtAccumulator = 0;
#fixedTimestep = 1 / 60;
@ -16,8 +16,9 @@ export class AnimationFrameController implements ReactiveController {
return this.#fixedTimestep;
}
#isRunning = false;
get isRunning() {
return this.#rAFId !== -1;
return this.#isRunning;
}
constructor(host: AnimationFrameControllerHost) {
@ -36,7 +37,7 @@ export class AnimationFrameController implements ReactiveController {
}
#tick = (timestamp: DOMHighResTimeStamp = performance.now()) => {
this.#rAFId = requestAnimationFrame(this.#tick);
requestAnimationFrame(this.#tick);
const actualDelta = (timestamp - this.#lastTime) * 0.001;
this.#lastTime = timestamp;
@ -56,10 +57,12 @@ export class AnimationFrameController implements ReactiveController {
if (this.isRunning) return;
this.#lastTime = 0;
requestAnimationFrame(this.#tick);
this.#isRunning = true;
this.#tick();
}
stop() {
cancelAnimationFrame(this.#rAFId);
cancelAnimationFrame(this.#tick);
this.#isRunning = false;
}
}

26
src/common/rAF.ts Normal file
View File

@ -0,0 +1,26 @@
const callbacks = new Set<FrameRequestCallback>();
let rAFId = -1;
function onRAF(time: DOMHighResTimeStamp) {
rAFId = -1;
const values = Array.from(callbacks);
callbacks.clear();
values.forEach((callback) => callback(time));
}
// Batch multiple callbacks into a single rAF for better performance
export function requestAnimationFrame(callback: FrameRequestCallback) {
if (callbacks.size === 0) {
rAFId = window.requestAnimationFrame(onRAF);
}
callbacks.add(callback);
}
export function cancelAnimationFrame(callback: FrameRequestCallback) {
callbacks.delete(callback);
if (callbacks.size === 0) {
window.cancelAnimationFrame(rAFId);
}
}