From 3ab3dab1b55b94575599dc4b6de46414584629c0 Mon Sep 17 00:00:00 2001 From: Dillion Verma Date: Fri, 27 Dec 2024 12:19:34 -0500 Subject: [PATCH] fix: update velocity scroll component --- .../docs/components/scroll-based-velocity.mdx | 12 +- .../example/scroll-based-velocity-demo.tsx | 9 +- .../default/magicui/scroll-based-velocity.tsx | 179 +++++++++--------- 3 files changed, 99 insertions(+), 101 deletions(-) diff --git a/content/docs/components/scroll-based-velocity.mdx b/content/docs/components/scroll-based-velocity.mdx index 1185c1016..5c5db23fb 100644 --- a/content/docs/components/scroll-based-velocity.mdx +++ b/content/docs/components/scroll-based-velocity.mdx @@ -48,9 +48,9 @@ npm install framer-motion ## Props -| Prop | Type | Description | Default | -| ---------------- | ------ | --------------------------------------------- | ------- | -| className | string | The class name to be applied to the component | | -| text | string | Text to be animated | "" | -| default_velocity | number | Base scroll velocity of text | 5 | -| rowsAmount | number | Number of rows to be animated | 1 | +| Prop | Type | Description | Default | +| --------------- | --------- | --------------------------------------------- | ------- | +| className | string | The class name to be applied to the component | | +| children | ReactNode | Content to be animated | | +| defaultVelocity | number | Base scroll velocity of text | 5 | +| numRows | number | Number of rows to be animated | 2 | diff --git a/registry/default/example/scroll-based-velocity-demo.tsx b/registry/default/example/scroll-based-velocity-demo.tsx index 5672abfb5..0fdb45b60 100644 --- a/registry/default/example/scroll-based-velocity-demo.tsx +++ b/registry/default/example/scroll-based-velocity-demo.tsx @@ -1,12 +1,5 @@ import { VelocityScroll } from "@/registry/default/magicui/scroll-based-velocity"; export default function ScrollBasedVelocityDemo() { - return ( - - ); + return Velocity Scroll; } diff --git a/registry/default/magicui/scroll-based-velocity.tsx b/registry/default/magicui/scroll-based-velocity.tsx index 3ce7ce55e..f27fcbca9 100644 --- a/registry/default/magicui/scroll-based-velocity.tsx +++ b/registry/default/magicui/scroll-based-velocity.tsx @@ -1,6 +1,5 @@ "use client"; -import React, { useEffect, useRef, useState } from "react"; import { motion, useAnimationFrame, @@ -10,20 +9,19 @@ import { useTransform, useVelocity, } from "framer-motion"; +import React, { useEffect, useRef, useState } from "react"; import { cn } from "@/lib/utils"; -interface VelocityScrollProps { - text: string; - default_velocity?: number; +interface VelocityScrollProps extends React.HTMLAttributes { + defaultVelocity?: number; className?: string; - rowsAmount?: number; + numRows?: number; } -interface ParallaxProps { - children: string; +interface ParallaxProps extends React.HTMLAttributes { + children: React.ReactNode; baseVelocity: number; - className?: string; } export const wrap = (min: number, max: number, v: number) => { @@ -31,93 +29,100 @@ export const wrap = (min: number, max: number, v: number) => { return ((((v - min) % rangeSize) + rangeSize) % rangeSize) + min; }; -export function VelocityScroll({ - text, - default_velocity = 5, - className, - rowsAmount = 1, -}: VelocityScrollProps) { - function ParallaxText({ - children, - baseVelocity = 100, - className, - }: ParallaxProps) { - 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(null); - const textRef = useRef(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 = React.useRef(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; +function ParallaxText({ + children, + baseVelocity = 100, + ...props +}: ParallaxProps) { + 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(null); + const textRef = useRef(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 = React.useRef(1); + useAnimationFrame((t, delta) => { + let moveBy = directionFactor.current * baseVelocity * (delta / 1000); - moveBy += directionFactor.current * moveBy * velocityFactor.get(); - - baseX.set(baseX.get() + moveBy); - }); - - return ( -
- - {Array.from({ length: repetitions }).map((_, i) => ( - - {children}{" "} - - ))} - -
- ); - } + 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 ( +
+ + {Array.from({ length: repetitions }).map((_, i) => ( + + {children}{" "} + + ))} + +
+ ); +} + +export function VelocityScroll({ + defaultVelocity = 5, + numRows = 2, + children, + className, + ...props +}: VelocityScrollProps) { return ( -
- {Array.from({ length: rowsAmount }).map((_, i) => ( +
+ {Array.from({ length: numRows }).map((_, i) => ( - {text} + {children} ))} -
+ ); }