mumtazded Posted December 31, 2024 Posted December 31, 2024 here's my React.js component: React, { useRef, useState, useEffect, useCallback } from "react"; import { Avatar, Card, CardBody, Typography } from "@material-tailwind/react"; import gsap from "gsap"; import { Draggable } from "gsap/all"; import { Quote } from "lucide-react"; import InertiaPlugin from "gsap-trial/InertiaPlugin"; // Register GSAP plugins if (typeof window !== "undefined") { gsap.registerPlugin(Draggable, InertiaPlugin); } interface ReviewsProps { data: CommentCardProps[]; } const Reviews: React.FC<ReviewsProps> = ({ data }: ReviewsProps) => { const wrapperRef = useRef<HTMLDivElement | null>(null); const itemsRef = useRef<HTMLDivElement[]>([]); // Initialize carouselData as an empty array to avoid null checks const [itemHeight, setItemHeight] = useState<number>(0); // Initialize windowWidth with a default value (e.g., 0) and update it in useEffect const [windowWidth, setWindowWidth] = useState<number>(0); // Measure the height of the carousel display after it mounts const measuredRef = useCallback((node: HTMLDivElement | null) => { if (node !== null) { setItemHeight(node.getBoundingClientRect().height); } }, []); // Add references to carousel items const addToRefs = useCallback((el: HTMLDivElement | null) => { if (el && !itemsRef.current.includes(el)) { itemsRef.current.push(el); } }, []); // Create GSAP animation timeline const createAnimation = ( carouselItems: HTMLDivElement[], width: number ): gsap.core.Timeline | undefined => { if (carouselItems.length > 0) { const timeline = gsap.timeline({ repeat: -1, paused: true }); timeline.to(carouselItems, { duration: 1, x: `+=${width}`, ease: "linear", overwrite: "auto", // repeat: -1, modifiers: { x: (x) => { const parsedX = parseFloat(x) % width; return `${parsedX}px`; }, }, }); return timeline.progress(1 / carouselItems.length); } return undefined; }; // Initialize carousel animation const carouselAnimation = useCallback(() => { const carouselItems = itemsRef.current; if (!carouselItems.length) return; const itemWidth = carouselItems[0].clientWidth; const carouselWidth = itemWidth * carouselItems.length; const snapBox = gsap.utils.snap(itemWidth); // Set initial positions of carousel items carouselItems.forEach((elm, i) => { gsap.set(elm, { x: i * itemWidth, left: -itemWidth }); }); // Set the height of the wrapper if (wrapperRef.current) { gsap.set(wrapperRef.current, { height: itemHeight }); } const wrapProgress = gsap.utils.wrap(0, 1); const proxy = document.createElement("div"); const timeline = createAnimation(carouselItems, carouselWidth); if (timeline) { Draggable.create(proxy, { trigger: "#elm", throwProps: true, inertia: true, dragResistance: 0.55, onDrag: updateProgress, onThrowUpdate: updateProgress, dragClickables: true, snap: { x: snapBox, // Ensure correct type }, }); } function updateProgress() { if (timeline) { const progress = gsap.getProperty(proxy, "x") as number; timeline.progress(wrapProgress(progress / carouselWidth)); } } }, [createAnimation, itemHeight]); // Set initial carousel data // Handle window resize and initialize carousel animation useEffect(() => { // Define a function to update window width const handleWindowResize = () => setWindowWidth(window.innerWidth); // Set initial window width handleWindowResize(); // Add resize event listener window.addEventListener("resize", handleWindowResize); // Initialize carousel animation carouselAnimation(); // Cleanup event listener on unmount return () => { window.removeEventListener("resize", handleWindowResize); }; }, [carouselAnimation]); return ( <div className="carousel-container-try" id="wrapper" ref={wrapperRef}> <div className="carousel-display-try h-96" ref={measuredRef}> {data.map((_, i) => ( <div key={i} id="elm" className="carousel-display-try__item" ref={addToRefs} > <CommentCard key={i} name={_.name} comment={_.comment} position={_.position} profile={_.profile} /> </div> ))} </div> </div> ); }; // {carouselData.map((item) => ( // <div // key={item} // id="elm" // className="carousel-display-try__item" // ref={addToRefs} // > // {item} // </div> // ))} type CommentCardProps = { name: string; position: string; comment: string; profile: string; }; function CommentCard({ comment, name, position, profile }: CommentCardProps) { return ( <> <Card className="py-2 px-4 w-96 bg-tertiary dark:bg-primary mx-2"> <CardBody className="flex flex-col justify-between gap-4"> <div className="flex items-start"> <Quote className="w-6 h-6 text-secondary" /> </div> <Typography className="text-lg text-secondary">{comment}</Typography> <div className="flex items-end"> <Quote className="w-6 h-6 text-secondary" /> </div> <hr className="my-2 h-[1px] border-t-0 bg-secondary" /> <div className="flex gap-4 items-center"> <Avatar src={profile} alt="astronout" /> <div className="flex flex-col gap-q"> <Typography className="text-lg font-bold text-secondary"> {name} </Typography> <Typography className="text-base text-secondary/50"> {position} </Typography> </div> </div> </CardBody> </Card> </> ); } export default Reviews; I want to use that inertia effect when I drag my content without InertiaPlugin, anyone maybe even tried that?
Rodrigo Posted December 31, 2024 Posted December 31, 2024 Not actually, that's the sole purpose of having the Inertia Plugin 😅, makes no sense to try to re-create it from scratch (as fun as the challenge is). Basically is like you going to the chicken place and asking for the secret recipe and if someone has tried to make the recipe from scratch after they already have it. Doesn't make a lot of sense to use a lot of time and effort in trying to do something that has already been done. Also keep in mind that the Inertia Plugin is just one of the many bonus Plugins you get when you sign up for the GSAP Club and a full year membership pays itself in one or two projects, after that is all profits for the rest of that year. Finally when working with React, we recommend using our useGSAP hook, you can learn more about it here: https://gsap.com/resources/React Happy Tweening!
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now