Skip to content

Instantly share code, notes, and snippets.

@gryzzly
Created March 4, 2024 21:54
Show Gist options
  • Save gryzzly/e758888a9ae6ebd725380fd0c8905a5e to your computer and use it in GitHub Desktop.
Save gryzzly/e758888a9ae6ebd725380fd0c8905a5e to your computer and use it in GitHub Desktop.
import { useEffect, useRef } from 'react';
type draw = (fraction: number) => void;
type duration = number;
const useAnimation = (duration: duration, draw: draw) => {
const updateDurationRef = useRef<null | ((newDuration: number) => void)>(null);
const currentAnimationIdRef = useRef(0);
const elapsedTimeRef = useRef(0);
useEffect(() => {
const animate = (duration: duration, draw: draw) => {
let start: number | null = null;
// let elapsedTime = 0;
const animation = (timestamp: number) => {
if (!start) start = timestamp;
elapsedTimeRef.current = timestamp - start;
const percentage = Math.min(elapsedTimeRef.current / duration, 1);
draw(percentage);
if (elapsedTimeRef.current < duration) {
currentAnimationIdRef.current = requestAnimationFrame(animation);
} else {
start = null;
currentAnimationIdRef.current = requestAnimationFrame(animation);
}
};
const updateDuration = (newDuration: number) => {
const currentProgress = elapsedTimeRef.current / duration;
start = performance.now() - newDuration * currentProgress;
duration = newDuration;
cancelAnimationFrame(currentAnimationIdRef.current);
currentAnimationIdRef.current = requestAnimationFrame(animation);
};
currentAnimationIdRef.current = requestAnimationFrame(animation);
return updateDuration;
};
updateDurationRef.current = animate(duration, draw);
return () => {
cancelAnimationFrame(currentAnimationIdRef.current);
};
}, [duration, draw]);
return updateDurationRef.current;
};
export { useAnimation };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment