I made this animation with framer-motion using the useAnimate hook because I thought it would be appropiate. It's basically an infinite word carousel. But I have no idea how to loop the animation infinitely.
import { useAnimate, cubicBezier } from "framer-motion";
import Image from "next/image";
import highlight from "@/public/highlight.svg";
import { useEffect, useRef } from "react";
const Heading = () => {
const [scope, animate] = useAnimate();
const isMounted = useRef(true);
const wordsHorizontal = ["Automate", "Enhance", "Streamline", "Automate"];
const wordsVertical = [
"Efficiency",
"Productivity",
"Performance",
"Efficiency",
];
useEffect(() => {
const handleAnim = async () => {
await animate(scope.current, { x: -525 }, { duration: 0.6, ease: cubicBezier(0.77,0,0.18,1), delay: 1});
await animate(scope.current, { x: -1050 }, { duration: 0.6, ease: cubicBezier(0.77,0,0.18,1), delay: 1});
await animate(scope.current, { x: -1575 }, { duration: 0.6, ease: cubicBezier(0.77,0,0.18,1), delay: 1});
await animate(scope.current, { x: 0 }, { duration: 0 });
};
handleAnim()
}, []);
return (
<div className="flex flex-col space-y-8">
<div className="flex space-x-6 items-start">
<div className="relative text-display font-bold w-[525px] h-[120px]">
<div className="absolute inset-0 bg-g-red rounded-3.5xl flex items-center overflow-hidden">
<div ref={scope} className="w-[2100px] flex">
{wordsHorizontal.map((word, index) => (
<div
key={index}
className="min-w-[525px] rounded-3.5xl flex items-center justify-center"
>
{word}
</div>
))}
</div>
...
I tried making the function call itself, or using an infinite for loop, while loop... etc.
Turn handleAnim
into a recursive function (a function that calls itself) and have it call itself after the last animation finishes. Framer Motion gives us a couple examples on how to run a function when an animation completes here. Here's how you can have your animation run infinitely:
useEffect(() => {
const handleAnim = async () => {
await animate(scope.current, { x: -525 }, { duration: 0.6, ease: cubicBezier(0.77,0,0.18,1), delay: 1});
await animate(scope.current, { x: -1050 }, { duration: 0.6, ease: cubicBezier(0.77,0,0.18,1), delay: 1});
await animate(scope.current, { x: -1575 }, { duration: 0.6, ease: cubicBezier(0.77,0,0.18,1), delay: 1});
await animate(scope.current, { x: 0 }, { duration: 0 });
// Run the animation function again
handleAnim()
};
handleAnim()
}, []);
Here is a working example. You can also read more about recursion in the MDN docs.