PreviewCodeEldora UI Eldora UI Installation pnpmnpmyarnbunpnpm add clsx framer-motion CopyCopy and paste the following code into your project.components/eldoraui/scrollbasedvelocity.tsx"use client"; "use client"; import React, { useEffect, useRef, useState } from "react"; import { motion, useAnimationFrame, useMotionValue, useScroll, useSpring, useTransform, useVelocity, } from "framer-motion"; import { cn } from "@/lib/utils"; interface VelocityScrollProps { text: string; default_velocity?: number; className?: string; } interface ParallaxProps { children: string; baseVelocity: number; className?: string; } export const wrap = (min: number, max: number, v: number) => { const rangeSize = max - min; return ((((v - min) % rangeSize) + rangeSize) % rangeSize) + min; }; export const VelocityScroll: React.FC<VelocityScrollProps> = ({ text, default_velocity = 5, className, }) => { const ParallaxText: React.FC<ParallaxProps> = ({ children, baseVelocity = 100, className, }) => { 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, }); const [repetitions, setRepetitions] = useState(1); const containerRef = useRef<HTMLDivElement>(null); const textRef = useRef<HTMLSpanElement>(null); useEffect(() => { const calculateRepetitions = () => { if (containerRef.current && textRef.current) { const containerWidth = containerRef.current.offsetWidth; const textWidth = textRef.current.offsetWidth; const newRepetitions = Math.ceil(containerWidth / textWidth) + 2; setRepetitions(newRepetitions); } }; calculateRepetitions(); window.addEventListener("resize", calculateRepetitions); return () => window.removeEventListener("resize", calculateRepetitions); }, [children]); const x = useTransform(baseX, (v) => `${wrap(-100 / repetitions, 0, v)}%`); const directionFactor = useRef<number>(1); useAnimationFrame((t, delta) => { let moveBy = directionFactor.current * baseVelocity * (delta / 1000); 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); }); return ( <div className="w-full overflow-hidden whitespace-nowrap" ref={containerRef} > <motion.div className={cn("inline-block", className)} style={{ x }}> {Array.from({ length: repetitions }).map((_, i) => ( <span key={i} ref={i === 0 ? textRef : null}> {children}{" "} </span> ))} </motion.div> </div> ); }; return ( <section className="relative w-full"> <ParallaxText baseVelocity={default_velocity} className={className}> {text} </ParallaxText> <ParallaxText baseVelocity={-default_velocity} className={className}> {text} </ParallaxText> </section> ); };CopyExpandUpdate the import paths to match your project setup. Props Prop NameTypeDefaultDescriptiontextstring-The text to scroll horizontally with velocity effect.default_velocitynumber5The default velocity for the scrolling effect.classNamestring""Additional CSS classes for custom styling.