From 619fae1ee288f34815532a3065195ba7f06e6a82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9Cchrisshank=E2=80=9D?= Date: Tue, 10 Dec 2024 13:05:00 -0800 Subject: [PATCH] optimize rAF calls --- src/common/animation-frame-controller.ts | 13 +++++++----- src/common/rAF.ts | 26 ++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 5 deletions(-) create mode 100644 src/common/rAF.ts diff --git a/src/common/animation-frame-controller.ts b/src/common/animation-frame-controller.ts index c372ded..6974f6f 100644 --- a/src/common/animation-frame-controller.ts +++ b/src/common/animation-frame-controller.ts @@ -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; } } diff --git a/src/common/rAF.ts b/src/common/rAF.ts new file mode 100644 index 0000000..2145899 --- /dev/null +++ b/src/common/rAF.ts @@ -0,0 +1,26 @@ +const callbacks = new Set(); +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); + } +}