assistant/renderer/components/particleLoop.ts

49 lines
1.4 KiB
TypeScript

/** Small scheduler shared by the two canvas treatments. Visibility and business
* state stay outside it; stopping an animation never stops a task. */
export function createParticleLoop({
draw, canRender, canAnimate,
requestFrame = requestAnimationFrame,
cancelFrame = cancelAnimationFrame,
}: {
draw: (elapsed: number, still: boolean) => void;
canRender: () => boolean;
canAnimate: () => boolean;
requestFrame?: (callback: FrameRequestCallback) => number;
cancelFrame?: (handle: number) => void;
}) {
let frame: number | null = null;
let previous: number | null = null;
let elapsed = 0;
let disposed = false;
function tick(now: number): void {
frame = null;
if (disposed || !canRender()) return;
if (!canAnimate()) { draw(elapsed, true); return; }
if (previous === null || now - previous >= 1000 / 30) {
elapsed += previous === null ? 0 : Math.min(now - previous, 75);
previous = now;
draw(elapsed, false);
}
frame = requestFrame(tick);
}
function sync(): void {
if (disposed) return;
if (frame !== null) cancelFrame(frame);
frame = null;
previous = null;
if (!canRender()) return;
draw(elapsed, !canAnimate());
if (canAnimate()) frame = requestFrame(tick);
}
function dispose(): void {
disposed = true;
if (frame !== null) cancelFrame(frame);
frame = null;
}
return { sync, dispose };
}