ryanmac
Content Type
Profiles
Forums
Store
Blog
Product
Showcase
FAQ
Downloads
Posts posted by ryanmac
-
-
-
Thank you! I went ahead and applied those changes but my events still seem to be firing twice. I moved the component to stackblitz so you could take a look.
https://stackblitzstarterskgd3hx-gyvp--3000--9e2d28a3.local-credentialless.webcontainer.io
UPDATE:
Figured it out. The solution, for my anyway, was to:1. attach the event listener directly on the element
2. create and leverage a ref array to grab the correct instance via index.
const itemRefs = useRef([]); const timelineRef = useRef(gsap.timeline({ paused: true })); const activeItem = useRef(null); itemRefs.current = []; const addToItemRefs = (el) => { if (el && !itemRefs.current.includes(el)) { itemRefs.current.push(el); } }; const toggleClick = (clickedItem) => { if (activeItem.current === clickedItem) { timelineRef.current.reverse(); return; } // timeline code...
<div className="skew-container grid grid-cols-4 gap-5 p-5 items-center h-full w-full"> {items.map((image, index) => ( <div ref={addToItemRefs} key={index} onClick={() => toggleClick(itemRefs.current[index])} className="skew-item bg-slate-500 min-h-[300px] h-full border-2 border-gray-900 rounded-lg overflow-hidden bg-cover bg-no-repeat" > <h2>{image.title}</h2> </div> ))} </div>
-
1
-
-
I can't figure out for the life of me why my component is initializing twice (and in the process registering event handlers twice that torch my animations). I thought the useGSAP hook mitigated this issue but perhaps I misunderstand or am utilizing it incorrectly.
Thanks in advance."use client" import React, { useRef } from "react"; import { gsap } from "gsap"; import { ScrollTrigger } from "gsap/ScrollTrigger"; import { useGSAP } from "@gsap/react"; import "./styles/skewgallery.css"; export const SkewGallery = ({ items }) => { gsap.registerPlugin(useGSAP, ScrollTrigger); const mainRef = useRef(); const overlayRef = useRef(); const timelineRef = useRef(null); useGSAP( (context, contextSafe) => { const itemsArray = gsap.utils.toArray(".skew-item"); console.log("initializing"); if (!timelineRef.current) { timelineRef.current = gsap.timeline({ paused: true }); } itemsArray.forEach((item) => { gsap.fromTo( item, { opacity: 0, yPercent: 20, ease: "power4.out", stagger: 1, }, { opacity: 1, yPercent: 0, scrollTrigger: { trigger: item, start: "top bottom", end: "50% 85%", scrub: 1, }, } ); const handleClick = contextSafe(() => { const timeline = timelineRef.current; console.log("doing it"); timeline.clear(); timeline.to( item, { rotation: 5, scale: 1.5, duration: 0.75, zIndex: 2, ease: "Back.easeOut", }, "<" ); timeline.to( overlayRef.current, { zIndex: 1, opacity: 0.85, }, "<" ); itemsArray.forEach((otherItem) => { if (otherItem !== item) { timeline.to( otherItem, { scale: 0.95, duration: 0.5, ease: "power2.out", }, "<" ); } }); timeline.play(); }); item.addEventListener("click", handleClick); return () => { item.removeEventListener("click", handleClick); }; }); console.log("overlay init"); overlayRef.current.addEventListener("click", () => { console.log("overlay clicked"); timelineRef.current.reverse(); }); }, { scope: mainRef, dependencies: [] } ); return ( <> <div ref={mainRef} className="skew"> <div ref={overlayRef} className="skew-overlay"></div> <div className="skew-container grid grid-cols-4 gap-5 p-5 items-center h-full w-full"> {items.map((image, index) => ( <div key={index} className="skew-item bg-slate-500 min-h-[300px] h-full border-2 border-gray-900 rounded-lg overflow-hidden bg-cover bg-no-repeat" > <h2>{image.title}</h2> </div> ))} </div> </div> </> ); }; export default SkewGallery;
Just subscribed to Club GSAP, issue generating an install token
in GSAP
Posted
Good to go, @Cassie. Thank you. 👍