I have created a ParallaxText with Framer-motion in which images move. This is the code for it:
import { useRef } from "react";
import {
motion,
useScroll,
useSpring,
useTransform,
useMotionValue,
useVelocity,
useAnimationFrame,
} from "framer-motion";
import { wrap } from "@motionone/utils";
interface ParallaxProps {
children: React.ReactNode;
baseVelocity: number;
}
const ParallaxText: React.FC<ParallaxProps> = ({
children,
baseVelocity = 100,
}) => {
const baseX = useMotionValue(0);
const { scrollY } = useScroll();
const scrollVelocity = useVelocity(scrollY);
const smoothVelocity = useSpring(scrollVelocity, {
damping: 50,
stiffness: 400,
});
const velocityFactor = useTransform(smoothVelocity, [0, 1000], [0, 5], {
clamp: false,
});
/**
* This is a magic wrapping for the length of the text - you
* have to replace for wrapping that works for you or dynamically
* calculate
*/
const x = useTransform(baseX, (v) => `${wrap(10, -15, v)}%`);
const directionFactor = useRef<number>(1);
useAnimationFrame((t, delta) => {
let moveBy = directionFactor.current * baseVelocity * (delta / 1000);
/**
* This is what changes the direction of the scroll once we
* switch scrolling directions.
*/
if (velocityFactor.get() < 0) {
directionFactor.current = -1;
} else if (velocityFactor.get() > 0) {
directionFactor.current = 1;
}
moveBy += directionFactor.current * moveBy * velocityFactor.get();
baseX.set(baseX.get() + moveBy);
});
/**
* The number of times to repeat the child text should be dynamically calculated
* based on the size of the text and viewport. Likewise, the x motion value is
* currently wrapped between -20 and -45% - this 25% is derived from the fact
* we have four children (100% / 4). This would also want deriving from the
* dynamically generated number of children.
*/
return (
<div className="overflow-hidden tracking-[-2px] leading-[0.8] m-0 whitespace-nowrap flex flex-nowrap">
<motion.div
className="scroller font-semibold uppercase text-[64px] flex flex-nowrap whitespace-nowrap"
style={{ x }}
>
<span>{children}</span>
<span>{children}</span>
<span>{children}</span>
<span>{children}</span>
</motion.div>
</div>
);
};
export default ParallaxText;
In the Page.tsx I call the ParallaxText, this is what the code looks like.
<section className="lg:pt-[12vh] lg:pb-[12vh] relative">
<ParallaxText baseVelocity={-5}>
<div className="flex">
<span className="block mr-[30px] grayscale">
<img src="/images/partner/sharp.png" alt="Sharp" />
</span>
<span className="block mr-[30px] grayscale">
<img src="/images/partner/brother.png" alt="Brother" />
</span>
</div>
</ParallaxText>
<ParallaxText baseVelocity={5}>
<div className="flex">
<span className="block mr-[30px] grayscale">
<img src="/images/partner/brother.png" alt="Brother" />
</span>
<span className="block mr-[30px] grayscale">
<img src="/images/partner/sharp.png" alt="Sharp" />
</span>
</div>
</ParallaxText>
</section>
My problem is that you can see how the pictures are removed and added again. But I want to have an infinite loop in which you can't see how the images are added and removed. I hope one of you can help me
I tried to change the value of the variable x but it didn't help much although I think it should help.