0

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.

New contributor
Leon Dertest is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.