Pierre Loti
Pierre Loti

Reputation: 133

Question about running multiple animations in sequence with Framer Motion

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

Answers (1)

Andrew Hulterstrom
Andrew Hulterstrom

Reputation: 1725

Luckily there is a fairly simple way to run multiple animations in framer motion and repeat the last one.

Updated Answer:

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).

Edit framer-motion sequence of animations framer-motion@10


Old Answer (framer-motion version 6):

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 the AnimationControls 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

Related Questions