I am trying to create a wavy text animation where I am getting the text from an array. And if the first text completes its animation then it should start hiding and another text from the array should start the animation.
codesandbox link: https://codesandbox.io/s/blazing-cdn-hjnxyh?file=/src/animated-text.jsx
CodePudding user response:
Since you have a two second duration with a 0.5 delay you can have a setInterval with an interval calculated from those two values on every step. Once you reach the last element you can clear your interval. The interval should just call setItems to update the state to the next value. I haven't tested anything nor I have some code to share but it sounds like a state update thing that can be handled in such way.
import { useEffect, useState } from "react";
import { motion } from "framer-motion";
const TextVariants = {
offscreen: {
opacity: 0
},
onscreen: {
opacity: 1
},
exit: {
opacity: 0
}
};
export default function FramerHeadline() {
const texts = ["react", "nextjs", "gatsby"];
const [currentWord, setCurrentWord] = useState(-1);
useEffect(() => {
let i = 0;
const interval = setInterval(() => {
if (i === texts.length) clearInterval(interval);
else setCurrentWord(i);
i ;
}, 2100 texts[i].length * 0.25);
return () => clearInterval(interval);
}, []);
return (
<motion.span
className="animated-headline"
transition={{ staggerChildren: 2 }}
>
{texts.map((word, index) => (
index === currentWord
? (<motion.span>
{word.split("").map((r, id) => (
<motion.span
initial="offscreen"
animate="onscreen"
exit="exit"
variants={TextVariants}
transition={{
duration: 2,
delay: id * 0.25
}}
key={index}
>
{r}
</motion.span>
))}
</motion.span>
)
: null
))}
</motion.span>
);
}