Search code examples
reactjsfrontendframer-motion

Framer Motion countdown animation is not precise


I'm trying to make a [n sec] countdown using Framer Motion in a React Application, but when I try to change the text displaying on the screen after the [n sec], the countdown gets to the 0 seconds before the text change happens.

Here's the code that makes that change:

const [status, setStatus] = useState("Waiting...");
const count = useMotionValue(5);
const time = useTransform(count, Math.round);

useEffect(() => {
    const animation = animate(count, 0, { duration: 5 });

    setTimeout(() => {
        setStatus("Finished!");
    }, 5 * 1000);

    return animation.stop;
}, []);

The GitHub repository to reproduce this is linked here: https://github.com/jpfragoso30/jp-framer-sandbox/tree/main

I've tried using the onUpdate method for animate to check if it's a problem of being async

const animation = animate(count, 0, { duration: 5, onUpdate: (value) => { if (value === 0) setStatus("Finished!"); }, });

And the .then for when the animation ends

const animation = animate(count, 0, { duration: 5, }).then(() => setStatus("Finished!"));;

In all of these attempts I'm just getting the same result, the "Finished!" text has a delay, and I don't think the animation is counting naturally if that makes sense.


Solution

  • Firstly, the method to transform your count value has to be ceiling to start counting at 0, at only go to 0 when you have an absolute zero

    const time = useTransform(count, Math.ceil);
    
    and also, to make the time go "natural", you must declare a "linear" movement
    
    const animation = animate(count, 0, {
                duration: 5,
                ease: "linear",
            }).then(() => setStatus("Finished!"));