web-player: split player, navigation and accent state into focused modules
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
const MAX_INTERPOLATION_SECONDS = 0.25;
|
||||
|
||||
export class ProgressClock {
|
||||
#rafId: number | null = null;
|
||||
#time = 0;
|
||||
#stamp = 0;
|
||||
|
||||
constructor(
|
||||
private getAudio: () => HTMLAudioElement | null,
|
||||
private onProgress: (seconds: number) => void
|
||||
) {}
|
||||
|
||||
#tick = (now: number) => {
|
||||
const audio = this.getAudio();
|
||||
if (!audio) return;
|
||||
if (audio.currentTime !== this.#time) {
|
||||
this.#time = audio.currentTime;
|
||||
this.#stamp = now;
|
||||
}
|
||||
const elapsed = Math.min(MAX_INTERPOLATION_SECONDS, (now - this.#stamp) / 1000);
|
||||
const smooth = this.#time + (audio.paused ? 0 : elapsed * audio.playbackRate);
|
||||
this.onProgress(Math.min(smooth, Number.isFinite(audio.duration) ? audio.duration : smooth));
|
||||
this.#rafId = requestAnimationFrame(this.#tick);
|
||||
};
|
||||
|
||||
start() {
|
||||
if (this.#rafId !== null) return;
|
||||
this.#rafId = requestAnimationFrame(this.#tick);
|
||||
}
|
||||
|
||||
stop() {
|
||||
if (this.#rafId === null) return;
|
||||
cancelAnimationFrame(this.#rafId);
|
||||
this.#rafId = null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user