Jump to content
Search Community

ryanmac

Premium
  • Posts

    4
  • Joined

  • Last visited

About ryanmac

ryanmac's Achievements

  1. Hi, recently signing up for the GSAP club but when I click the "generate token" button it acts as if it's generating one, then briefly displays "Success" before the button returns to the initial state with no token displayed. Tried on a few browsers and phone.
  2. 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>
  3. 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;
×
×
  • Create New...