Pavel Buchta Posted July 2 Share Posted July 2 It works, but I'm not sure whether I should do it like this or using useGSAP hook. And if I should use it with useGSAP hook then how to do it precicely? useEffect(() => { const observer = ScrollTrigger.observe({ target: container.current, onHover: () => setHover(true), onHoverEnd: () => setHover(false), }); return () => { observer.kill(); }; }, []); I looked at the documentation, but I couldn't find how to use it in next.js. Link to comment Share on other sites More sharing options...
Solution Rodrigo Posted July 2 Solution Share Posted July 2 Hi, An Observer Plugin instance is no different than any other GSAP instance, so is better to handle it in the same way we suggest in our learning center, that is using the useGSAP hook for it: useGSAP(() => { const myObserver = Observer.create({ ... }); }); Now based on the code you're passing I'm not 100% sure what's the idea, since you're updating a state property, probably I'd try to solve that using React's synthetic events instead of Observer. Now if your code works as expected, then just keep it: "If is not broken, don't fix it". Happy Tweening! Link to comment Share on other sites More sharing options...
Pavel Buchta Posted July 3 Author Share Posted July 3 Thanks Rodrigo, that is all I needed. 8 hours ago, Rodrigo said: I'd try to solve that using React's synthetic events instead of Observer. This is my code. The reason I did not do it simplfy by onMouseEnter is, that when I scrolled out of hovering it still kept the custom cursor visible. However now, when I scroll out of hovering the element it sets the state to false. "use client"; import { CONTACT_URL } from "@/config"; import { useGSAP } from "@gsap/react"; import clsx from "clsx"; import gsap from "gsap"; import { ScrollTrigger } from "gsap/ScrollTrigger"; import Link from "next/link"; import { useRef, useState } from "react"; import CustomHoverCursor from "./custom-hover-cursor"; export default function Marquee() { const [hover, setHover] = useState(false); const container = useRef(null); const animationRef = useRef(null); useGSAP( () => { gsap.to(animationRef.current, { x: -600, scrollTrigger: { trigger: animationRef.current, scrub: true, start: "top 100%", end: "bottom 0%", // markers: true, }, }); }, { scope: container } ); useGSAP( () => { const animation = gsap.to(animationRef.current, { xPercent: -40.5, repeat: -1, duration: 10, ease: "linear", scrollTrigger: { trigger: container.current, start: "top 100%", end: "bottom 0%", onUpdate: (self) => { animation.reversed(self.direction === 1 ? false : true); }, }, }); }, { scope: container } ); useGSAP(() => { ScrollTrigger.observe({ target: container.current, onHover: () => setHover(true), onHoverEnd: () => setHover(false), }); }, []); return ( <section ref={container} className="mb-12 mt-40 flex w-full items-center justify-center" > <CustomHoverCursor active={hover} /> <Link href={CONTACT_URL} className={clsx("relative w-full overflow-hidden", { "text-accend": hover, "text-foreground": !hover, })} > <div className="flex w-fit items-center justify-center gap-6 lg:gap-12" ref={animationRef} style={ { // animationDirection: direction === "right" ? "normal" : "reverse", // animationIterationCount: "infinite", // animationDuration: "15s", // animationTimingFunction: "linear", // animationName: "marqueeAnimation", } } > {Array.from({ length: 5 }).map((_, index) => ( <div className="flex items-center gap-6 whitespace-nowrap text-[calc(40px*1.5)] font-semibold tracking-tighter duration-300 lg:gap-12 lg:text-[calc(40px*3)]" key={index} > <div className="text-[calc(24px*2.5)] lg:text-[calc(24px*3)]"> ✦ </div> Get in touch </div> ))} </div> </Link> </section> ); } 1 Link to comment Share on other sites More sharing options...
Rodrigo Posted July 3 Share Posted July 3 Hi, Is great to hear that is working as expected, the only thing caught my attention in your code is this: useGSAP( () => { gsap.to(animationRef.current, { x: -600, scrollTrigger: { trigger: animationRef.current, scrub: true, start: "top 100%", end: "bottom 0%", // markers: true, }, }); }, { scope: container } ); useGSAP( () => { const animation = gsap.to(animationRef.current, { xPercent: -40.5, repeat: -1, duration: 10, ease: "linear", scrollTrigger: { trigger: container.current, start: "top 100%", end: "bottom 0%", onUpdate: (self) => { animation.reversed(self.direction === 1 ? false : true); }, }, }); }, { scope: container } ); You're creating two different animations with the same target animationRef.current and basically the same ScrollTrigger configuration, at least when it comes to the trigger, start and end. Also on both animations you're animating the same element on the X axis, granted that those are different properties but that looks odd. You should review that and see if you can had all that logic in just one instance of the useGSAP hook and control everything with just a single ScrollTrigger. Happy Tweening! 1 Link to comment Share on other sites More sharing options...
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