import { ref , isRef , computed , onMounted , onUnmounted , Ref } from '@src/api' ; export type TFps = number | Ref < number > ; const getFps = ( fps ) => Number ( isRef ( fps ) ? fps . value : fps ) ; const calcFpsInterval = ( fps ) => 1000 / fps ; const fpsLimit = 60 ; export function useRafFn ( callback , fps = fpsLimit , runOnMount = true ) { const isRunning = ref ( false ) ; const fpsInterval = computed ( ( ) => calcFpsInterval ( getFps ( fps ) ) ) ; let itWasIdle = false ; let startTime = 0 ; let timeElapsed = 0 ; let timePausedTot = 0 ; let timeDelta = 0 ; const loop = ( timeStamp ) => { if ( ! startTime ) startTime = timeStamp ; if ( ! isRunning . value ) return ; if ( itWasIdle ) { timePausedTot = timeStamp - startTime - timeElapsed ; itWasIdle = false ; } timeElapsed = timeStamp - startTime - timePausedTot ; const callbackShouldAlwaysRun = getFps ( fps ) >= fpsLimit ; if ( callbackShouldAlwaysRun ) { timeDelta = timeElapsed ; callback ( timeElapsed ) ; } if ( ! callbackShouldAlwaysRun ) { const elapsedTimeFromPrevLoop = Math . ceil ( timeElapsed - timeDelta ) ; if ( elapsedTimeFromPrevLoop > fpsInterval . value ) { timeDelta = timeElapsed ; callback ( timeElapsed ) ; } } requestAnimationFrame ( loop ) ; } ; const start = ( ) => { isRunning . value = true ; requestAnimationFrame ( loop ) ; } ; const stop = ( ) => { isRunning . value = false ; itWasIdle = true ; } ; onMounted ( ( ) => runOnMount && start ( ) ) ; onUnmounted ( stop ) ; return { isRunning , start , stop } ; }