skip to Main Content

I’m trying to do a "text slideshow" where a text appears, stays on screen for a few seconds, then disappears to show another text. I’m doing this with framer-motion.

The problem is that my text, supposed to start from x: 200, go to 0 then go to x: -200 with the exit motion prop, just goes from 200 to 0 and repeats (it does not go the other way like intended).

How could I programmatically trigger the exit state? And how could I add another text when the first one goes off?

<AnimatePresence mode={"wait"}>
   <motion.span
      key={"123"}
      initial={{ x: 200 }}
      animate={{ x: 0 }}
      exit={{ x: "-200px" }}
      transition={{
         repeat: Infinity,
      }}
   >
      456
   </motion.span>
</AnimatePresence>

Codesandbox for everything, including the to-do and the steps: https://codesandbox.io/s/wizardly-joliot-ndzftw?file=/src/Animation.js

Here are the requirements written in the above Sandbox link:

  • [x] the text must transition into the veiw
  • [x] the text must stay in for, say, 2 secs
  • [ ] the text must go out and disappear with its exit animation
  • [ ] another text must take its place
  • [ ] the whole thing must loop

2

Answers


  1. just add repeatDelay: 1

    <AnimatePresence mode={"wait"}>
       <motion.span
          key={"123"}
          initial={{ x: 200 }}
          animate={{ x: 0 }}
          exit={{ x: "-200px" }}
          transition={{
             repeat: Infinity,
             // it works!
             repeatDelay: 1
          }}
       >
          456
       </motion.span>
    </AnimatePresence>
    
    Login or Signup to reply.
  2. You won’t be able to do everything you want just with Framer animations.

    Since you want the text to change each time, it might help to not think of it as animating a single item in a loop, but animating multiple individual items in and out in sequence.

    First you’ll need to keep track of some state so you know what text to display.

    And instead of relying on the Framer animations for timing, you can create an interval that fires repeatedly and triggers the transition from one item to the next:

    // keep a counter of the number of cycles
    const [count, setCount] = React.useState(1);
    
    // set an interval to cycle the animation every 3 seconds
    React.useEffect(() => {
      const timer = setInterval(() => {
        setCount(count + 1);
      }, 3000);
      // clearing interval
      return () => clearInterval(timer);
    });
    

    You can use the count state to determine which text to display, and you can also use it as the key prop.

    Now when the count ticks up, the key changes, and React will interpret that as having removed the old item from the page (triggering the exit animation) and adding a new item, with a new key (triggering the enter animation).

    <motion.span
      className={"el1"}
      key={count} // use `count` for key
      initial={{ y: 200 }}
      animate={{ y: 0 }}
      exit={{ y: -200 }}
    >
    

    Since you’re now animating multiple elements (instead of looping one) you can remove the repeat transition.

    You’ll most likely want to wait for the exit animation of the old item to finish before adding the new item to the page to prevent things from shifting around. You can do that by adding mode="wait" to the AnimatePresence tag:

    <AnimatePresence mode="wait">
    

    Here’s a working version of your Code Sandbox

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search