import { FrameTickrSettings } from "./types" ; import { createFrameTiming } from "./timing" ; export type RawFrameTickrSettings = Partial < FrameTickrSettings > & Pick < FrameTickrSettings , "frame" > ; /**
 * Runs a callback on a roughly precise interval.
 */ export class FrameTickr { /**
     * Settings used for initialization.
     */ private readonly settings : FrameTickrSettings ; /**
     * Reference to the next tick from `requestFrame`.
     */ private nextTickHandle : unknown ; /**
     * Whether frame execution is currently paused.
     */ private paused : boolean ; /**
     * The most recent timestamp this was run at, if ever.
     */ private previousTimestamp ? : number ; param settings public constructor ( rawSettings ) { const timing = rawSettings . timing ?? createFrameTiming ( ) ; this . settings = { events : { } , interval : 1000 / 60 , ... rawSettings , timing , } ; this . paused = true ; } returns public getInterval ( ) { return this . settings . interval ; } returns public getPaused ( ) { return this . paused ; } /**
     * Stops execution of frames.
     */ public pause ( ) { if ( this . paused ) { return ; } this . paused = true ; this . previousTimestamp = undefined ; this . settings . timing . cancelFrame ( this . nextTickHandle ) ; this . settings . events ?. pause ?. ( ) ; } /**
     * Starts execution of frames.
     */ public play ( ) { if ( ! this . paused ) { return ; } this . paused = false ; this . attemptTick ( this . settings . timing . getTimestamp ( ) ) ; this . settings . events ?. play ?. ( ) ; } param interval public setInterval ( interval ) { if ( isNaN ( interval ) ) { throw new Error ( `Invalid interval given to setInterval: '${ interval }'.` ) ; } this . settings . interval = interval ; } param timestamp private readonly attemptTick = ( timestamp ) : void => { if ( this . paused ) { return ; } this . nextTickHandle = this . settings . timing . requestFrame ( this . attemptTick ) ; if ( this . previousTimestamp === undefined ) { this . runFrame ( timestamp ) ; return ; } const timestampDelta = timestamp - this . previousTimestamp ; if ( timestampDelta < this . settings . interval ) { return ; } this . runFrame ( timestamp - ( timestampDelta - this . settings . interval ) ) ; } ; param adjustedTimestamp private runFrame ( adjustedTimestamp ) { this . previousTimestamp = adjustedTimestamp ; this . settings . frame ( adjustedTimestamp ) ; } }