Skip to content

Instantly share code, notes, and snippets.

@bigtimebuddy
Last active September 28, 2023 17:17
Show Gist options
  • Save bigtimebuddy/f8f46289d77b7c6dd73130030adcb888 to your computer and use it in GitHub Desktop.
Save bigtimebuddy/f8f46289d77b7c6dd73130030adcb888 to your computer and use it in GitHub Desktop.
Simple shared ticker for wrapping a single requestAnimationFrame
interface Tickerable {
render(time: number): void;
}
/**
* Create a shared, static frame ticker. Using many requestAnimationFrame
* callbacks can be a performance killer, so this wraps multiple targets
* with a single requestAnimationFrame call.
*/
class Ticker {
static #tick: number = 0;
static #targets: Tickerable[] = [];
/** Add an object to tick */
static add(target: Tickerable) {
this.remove(target);
this.#targets.push(target);
this.#startLoop();
}
/** Remove an object from ticking */
static remove(target: Tickerable) {
const index = this.#targets.indexOf(target);
if (index > -1) {
this.#targets.splice(index, 1);
}
if (!this.#targets.length) {
this.#stopLoop();
}
}
/** Internally start the animation loop */
static #startLoop() {
this.#stopLoop();
this.#tick = requestAnimationFrame((time) => {
this.#targets.forEach((target) => target.render(time));
this.#startLoop();
});
}
/** Internally stop the animation loop */
static #stopLoop() {
if (this.#tick) {
cancelAnimationFrame(this.#tick);
}
this.#tick = 0;
}
}
export { Ticker };
export type { Tickerable };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment