UNPKG

tempus

Version:
226 lines (224 loc) 6.19 kB
// packages/core/src/clock.ts var Clock = class { _elapsed = 0; _currentTime = 0; _startTime = void 0; _lastTime = void 0; _isPlaying = false; _deltaTime = 0; play() { if (this._isPlaying) return; this._currentTime = 0; this._startTime = void 0; this._isPlaying = true; } pause() { if (!this._isPlaying) return; this._deltaTime = 0; this._isPlaying = false; } reset() { this._elapsed = 0; this._deltaTime = 0; this._currentTime = 0; this._lastTime = void 0; this._isPlaying = false; } update(browserTime) { if (!this._isPlaying) return; if (!this._startTime) { this._startTime = browserTime; } if (this._lastTime === void 0) { this._lastTime = this._startTime; this._currentTime = 0; this._deltaTime = 0; } else { this._lastTime = this._currentTime; this._currentTime = browserTime - this._startTime; this._deltaTime = this._currentTime - this._lastTime; this._elapsed += this._deltaTime; } } get time() { return this._elapsed; } get isPlaying() { return this._isPlaying; } get deltaTime() { return this._deltaTime; } }; // packages/core/src/uid.ts var index = 0; function getUID() { return index++; } // packages/core/src/tempus.ts var isClient = typeof window !== "undefined"; var originalRAF = isClient && window.requestAnimationFrame; var originalCancelRAF = isClient && window.cancelAnimationFrame; var Framerate = class { callbacks = []; fps; time = 0; lastTickDate = performance.now(); framesCount = 0; constructor(fps = Number.POSITIVE_INFINITY) { this.fps = fps; } get isRelativeFps() { return typeof this.fps === "string" && this.fps.endsWith("%"); } get maxFramesCount() { if (!this.isRelativeFps) return 1; return Math.max(1, Math.round(100 / Number(this.fps.replace("%", "")))); } get executionTime() { if (this.isRelativeFps) return 0; return 1e3 / this.fps; } dispatch(time, deltaTime) { for (let i = 0; i < this.callbacks.length; i++) { const now = performance.now(); this.callbacks[i]?.callback(time, deltaTime); const duration = performance.now() - now; this.callbacks[i].samples?.push(duration); this.callbacks[i].samples = this.callbacks[i].samples?.slice(-9); } } raf(time, deltaTime) { this.time += deltaTime; if (this.isRelativeFps) { if (this.framesCount === 0) { this.dispatch(time, deltaTime); } this.framesCount++; this.framesCount %= this.maxFramesCount; } else { if (this.fps === Number.POSITIVE_INFINITY) { this.dispatch(time, deltaTime); } else if (this.time >= this.executionTime) { this.time = this.time % this.executionTime; const deltaTime2 = time - this.lastTickDate; this.lastTickDate = time; this.dispatch(time, deltaTime2); } } } add({ callback, priority, label }) { if (typeof callback !== "function") { console.warn("Tempus.add: callback is not a function"); return; } const uid = getUID(); this.callbacks.push({ callback, priority, uid, label, samples: [] }); this.callbacks.sort((a, b) => a.priority - b.priority); return () => this.remove(uid); } remove(uid) { this.callbacks = this.callbacks.filter(({ uid: u }) => uid !== u); } }; var TempusImpl = class { framerates = {}; clock = new Clock(); fps; usage = 0; rafId; constructor() { if (!isClient) return; this.play(); } restart() { if (this.rafId) { cancelAnimationFrame(this.rafId); } for (const framerate of Object.values(this.framerates)) { framerate.framesCount = 0; framerate.time = 0; framerate.lastTickDate = performance.now(); } this.clock.reset(); this.play(); } play() { if (!isClient || this.clock.isPlaying) return; this.clock.play(); this.rafId = requestAnimationFrame(this.raf); } pause() { if (!isClient || !this.rafId || !this.clock.isPlaying) return; cancelAnimationFrame(this.rafId); this.rafId = void 0; this.clock.pause(); } get isPlaying() { return this.clock.isPlaying; } add(callback, { priority = 0, fps = Number.POSITIVE_INFINITY, label = "" } = {}) { if (!isClient) return; if (typeof fps === "number" || typeof fps === "string" && fps.endsWith("%")) { if (!this.framerates[fps]) this.framerates[fps] = new Framerate(fps); return this.framerates[fps].add({ callback, priority, label }); } console.warn('Tempus.add: fps is not a number or a string ending with "%"'); } raf = (browserElapsed) => { if (!isClient) return; this.clock.update(browserElapsed); const elapsed = this.clock.time; const deltaTime = this.clock.deltaTime; this.fps = 1e3 / deltaTime; const now = performance.now(); for (const framerate of Object.values(this.framerates)) { framerate.raf(elapsed, deltaTime); } const duration = performance.now() - now; this.usage = duration / deltaTime; this.rafId = requestAnimationFrame(this.raf); }; patch() { if (!isClient) return; window.requestAnimationFrame = (callback, { priority = 0, fps = Number.POSITIVE_INFINITY } = {}) => { if (callback === this.raf || !callback.toString().includes("requestAnimationFrame(")) { return originalRAF(callback); } if (!callback.__tempusPatched) { callback.__tempusPatched = true; callback.__tempusUnsubscribe = this.add(callback, { priority, fps, label: callback.name }); } return callback.__tempusUnsubscribe; }; window.cancelAnimationFrame = (callback) => { if (typeof callback === "function") { callback?.(); return; } return originalCancelRAF(callback); }; } unpatch() { if (!isClient) return; window.requestAnimationFrame = originalRAF; window.cancelAnimationFrame = originalCancelRAF; } }; var Tempus = new TempusImpl(); export { Tempus as default }; //# sourceMappingURL=tempus.mjs.map