export class StopWatch { private startTime : number ; private running : boolean ; private elapsed : number ; constructor ( ) { this . startTime = 0 ; this . elapsed = 0 ; this . running = false ; } public start ( ) { this . startTime = Date . now ( ) ; this . running = true ; this . elapsed = 0 ; } public stop ( ) { this . running = false ; this . elapsed = Date . now ( ) - this . startTime ; } public getElapsedTime ( ) { return this . running ? Date . now ( ) - this . startTime : this . elapsed ; } public reset ( ) { this . startTime = Date . now ( ) ; this . elapsed = 0 ; } public isRunning ( ) { return this . running ; } } export class AnimationTimer extends StopWatch { duration : number ; transducer : ( percent : number ) => number ; constructor ( duration = 1000 , transducer = AnimationTimer . makeLinear ( ) ) { super ( ) ; this . duration = duration ; this . transducer = transducer ; } public getElapsedTime ( ) { if ( ! this . isRunning ( ) || ! this . duration ) { return 0 ; } let elapsed = super . getElapsedTime ( ) ; let percentComplete = elapsed / this . duration ; return elapsed * ( this . transducer ( percentComplete ) / percentComplete ) ; } public isExpired ( ) { return this . getElapsedTime ( ) > this . duration ; } static makeLinear ( ) { return function ( percentComplete ) { return percentComplete ; } ; } static makeEaseIn ( strength = 1 ) { return function ( percentComplete ) { return Math . pow ( percentComplete , strength * 2 ) ; } ; } static makeEaseOut ( strength = 1 ) { return function ( percentComplete ) { return 1 - Math . pow ( 1 - percentComplete , strength * 2 ) ; } ; } static makeEaseInOut ( ) { return function ( percentComplete ) { return percentComplete - Math . sin ( percentComplete * 2 * Math . PI ) / ( 2 * Math . PI ) ; } ; } static makeElastic ( passes = 3 ) { return function ( percentComplete ) { return ( 1 - Math . cos ( percentComplete * Math . PI * passes ) ) * ( 1 - percentComplete ) + percentComplete ; } ; } static makeBounce ( bounces ) { let fn = AnimationTimer . makeElastic ( bounces ) ; return function ( percentComplete ) { percentComplete = fn ( percentComplete ) ; return percentComplete <= 1 ? percentComplete : 2 - percentComplete ; } ; } } class TimeSystem { private transducerStartTime : number ; private elapsed : number ; public isStart : boolean ; public isPaused : boolean ; public transducer : ( now : number ) => number ; constructor ( ) { this . elapsed = 0 ; this . isPaused = false ; this . isStart = false ; this . transducer = ( elapsed ) => elapsed ; this . transducerStartTime = 0 ; } private calculateElapsed ( now ) { let { transducerStartTime , transducer , isPaused } = this ; if ( ! this . isPaused ) { let transducerElapsed = now - transducerStartTime ; if ( typeof transducer === 'function' ) { transducerElapsed = transducer ( transducerElapsed ) ; } this . elapsed += transducerElapsed ; this . transducerStartTime = now ; } } public start ( now = Date . now ( ) ) { if ( now == undefined ) { now = Date . now ( ) ; } this . elapsed = 0 ; this . isStart = true ; this . transducerStartTime = now ; } public reset ( ) { this . elapsed = 0 ; this . isStart = false ; this . transducerStartTime = Date . now ( ) ; } public paused ( now = Date . now ( ) ) { if ( now == undefined ) { now = Date . now ( ) ; } if ( ! this . isPaused ) { this . calculateElapsed ( now ) ; this . isPaused = true ; } } public unPaused ( ) { if ( this . isPaused ) { this . transducerStartTime = Date . now ( ) ; this . isPaused = false ; } } public getElapsed ( now = Date . now ( ) ) { let { transducerStartTime , transducer , isPaused } = this ; if ( this . isPaused ) { return this . elapsed ; } let transducerElapsed = now - transducerStartTime ; if ( typeof transducer === 'function' ) { transducerElapsed = transducer ( transducerElapsed ) ; } return this . elapsed + transducerElapsed ; } public setTransducer ( transducerFunction , duration ? , now = Date . now ( ) ) { let { transducer } = this ; this . calculateElapsed ( now ) ; this . transducer = transducerFunction ; if ( Number . isFinite ( duration ) ) { setTimeout ( this . setTransducer . bind ( this , transducer ) , duration ) ; } } static ; } export default TimeSystem ;