Jump to content
Search Community

How to use Observer in next.js?

Pavel Buchta test
Moderator Tag

Go to solution Solved by Rodrigo,

Recommended Posts

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

  • Solution

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

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>
  );
}

 

  • Like 1
Link to comment
Share on other sites

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!

  • Like 1
Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...