useRequestAnimationFrame

Jun 24, 2024
export function useRequestAnimationFrame(callback: () => void, fps: number = 60) {
  const rafRef = useRef<number>(0)
  const lastFrameTimeRef = useRef<number>(0)

  const animate = useCallback((timestamp: DOMHighResTimeStamp) => {
    if (!lastFrameTimeRef.current) {
      lastFrameTimeRef.current = timestamp
    }

    const timeSinceLastFrame = timestamp - lastFrameTimeRef.current
    const frameInterval = 1000 / fps

    if (timeSinceLastFrame >= frameInterval) {
      lastFrameTimeRef.current = timestamp
      callback()
    }

    rafRef.current = requestAnimationFrame(animate)
  }, [callback, fps])

  useEffect(() => {
    rafRef.current = requestAnimationFrame(animate)
    return () => cancelAnimationFrame(rafRef.current)
  }, [animate])
}