@nent/core
Version:
86 lines (85 loc) • 3.15 kB
JavaScript
/*!
* NENT 2022
*/
import { debugIf, EventEmitter, throttle, } from '../../../services/common';
import { TIMER_EVENTS, } from '../../n-presentation/services/interfaces';
import { getTimeDetails } from '../../n-presentation/services/time';
/* It's a timer that uses the browser's animation frame to emit events at a given interval */
export class FrameTimer extends EventEmitter {
/**
* It creates a new timer object that will fire an event every `interval` milliseconds, and will fire
* a final event when the timer has run for `durationSeconds`
* @param {AnimationFrameProvider} provider - AnimationFrameProvider
* @param {number} interval - The interval at which to emit the current time.
* @param {number} durationSeconds - The duration of the timer in seconds.
* @param getStart - () => number = performance.now,
* @param {null | (() => void)} [onInterval=null] - a callback that will be called every interval
* milliseconds.
* @param {boolean} [debug=false] - boolean - if true, will log to console.log
*/
constructor(provider, interval, durationSeconds, getStart = performance.now, onInterval = null, debug = false) {
super();
this.provider = provider;
this.interval = interval;
this.durationSeconds = durationSeconds;
this.getStart = getStart;
this.onInterval = onInterval;
this.debug = debug;
this.timer = 0;
this.start = 0;
this.durationMs = 0;
this.durationMs = this.durationSeconds * 1000;
debugIf(this.debug, `presentation-timer: starting timer w/ ${this.durationSeconds} duration`);
this.currentTime = getTimeDetails(this.start, this.start, this.durationMs);
if (this.interval > 0)
this.debouncedInterval = throttle(this.interval, () => {
this.timer = this.provider.requestAnimationFrame(current => {
this.doInterval(current);
});
}, true, true);
else
this.debouncedInterval = () => {
this.timer = this.provider.requestAnimationFrame(current => {
this.doInterval(current);
});
};
}
/**
* We start the timer by setting the start time, and then we call the `doInterval` function
*/
begin() {
if (this.timer)
this.stop();
this.start = this.getStart();
this.currentTime = getTimeDetails(this.start, this.start, this.durationMs);
this.provider.requestAnimationFrame(async (current) => {
await this.doInterval(current);
});
}
/**
* It stops the animation by cancelling the requestAnimationFrame
*/
stop() {
this.provider.cancelAnimationFrame(this.timer);
}
async doInterval(time) {
var _a;
this.currentTime = getTimeDetails(this.start, time, this.durationMs);
if (this.currentTime.ended) {
this.stop();
this.emit(TIMER_EVENTS.OnEnd, this.currentTime);
}
else {
this.emit(TIMER_EVENTS.OnInterval, this.currentTime);
await this.debouncedInterval();
}
(_a = this.onInterval) === null || _a === void 0 ? void 0 : _a.call(this);
}
/**
* It stops the timer and removes all listeners.
*/
destroy() {
this.stop();
this.removeAllListeners();
}
}