Reputation: 133
I've only been using Framer Motion since today, and I wanted to know if it was possible to run several animations on an image and repeat one in particular. Basically, I would like to make an image move and then do a gravity effect on it.
Upvotes: 8
Views: 13262
Reputation: 1725
Luckily there is a fairly simple way to run multiple animations in framer motion and repeat the last one.
We can use the useAnimate()
hook to orchestrate complex animations in sequence.
First use the useAnimate()
hook to get the scope
and animate
objects:
const [scope, animate] = useAnimate();
Then we will connect a <motion.div>
to the hook using the scope
as a ref:
<motion.div
ref={scope}
...
/>
Next we set up the animation sequence we want to follow. Notice that on the final animate
call we have set the option repeat
to Infinity
so it will repeat forever.
async function myAnimation() {
await animate(scope.current, { rotate: -90 });
await animate(scope.current, { scale: 1.5 });
await animate(scope.current, { rotate: 0 });
await animate(scope.current, { scale: 1 });
animate(
scope.current,
{
x: 100
},
{
repeat: Infinity,
repeatType: "mirror",
ease: "easeInOut",
duration: 1
}
);
}
The last step is to call myAnimation()
when the page first loads to start the animation sequence:
useEffect(() => {
myAnimation();
}, []);
Here is a codesandbox to show all of these parts together, (including an example of multiple repeating animations).
With the
useAnimation()
hook we can set up component animation controls and then have the ability to do any animations we want in sequence.First make sure to create an
AnimationControls
object:
const animationControls = useAnimation();
Then we will set up our
<motion.div>
to use theAnimationControls
object we made:<motion.div style={{ width: 150, height: 150, borderRadius: 30, backgroundColor: "#fff", }} animate={animationControls} // This will let us control the animation using the animationControls object /> ``` Next we set up the animation sequence we want to follow. Notice that on the final `.start` call we have set `transition` to have a property of `repeat: Infinity` so it will repeat forever. ``` async function sequence() { await animationControls.start({ rotate: -90 }); await animationControls.start({ scale: 1.5 }); await animationControls.start({ rotate: 0 }); await animationControls.start({ scale: 1 }); animationControls.start({ x: 100, transition: { ease: "easeInOut", duration: 1, repeat: Infinity, repeatType: "reverse" } }); } ``` The last step is simply to call `sequence()` when the page mounts which will start the animation: ``` useEffect(() => { sequence(); }, []); ``` Here is a [codesandbox](https://codesandbox.io/s/framer-motion-sequence-of-animations-1uobnf?file=/src/App.js) to show all of these parts together. [![Edit framer-motion sequence of animations](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/framer-motion-sequence-of-animations-1uobnf?fontsize=14&hidenavigation=1&theme=dark)
Upvotes: 15