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:
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