Jump to content
Search Community

React/NextJS + ScrollSmoother + ScrollTrigger

OSITAKA test
Moderator Tag

Go to solution Solved by GreenSock,

Recommended Posts

Hello,

I am using ScrollSmoother and ScrollTrigger for the "first time" and I am now on a point that I really need to reach out for help. (I have a codesandbox link below)

 

Before I describe my problem, I would like to show what I have done so far: https://dlw-digital-website.netlify.app/home-desktop 

 

1 – ScrollSmoother:

When compared with a desktop, a mobile device will have always less power and performance. I would like to initiate the ScrollSmoother only for non-mobile devices. What I mean by "non-mobile" devices are: Desktops/Laptops and Smart TV's (doesn't really matter if these devices are `touch` or not). The main idea is to have a more "cheap performance scrolling" for mobiles, by disabling the ScrollSmoother and add some "in view" CSS animations (for example, a simpler fade-in).

 

So far I was able to use `if (ScrollTrigger.isTouch === 0) {` or `mm.add("(min-width: 600px)", () => {` but this doesn't really works for the Smart TV's. Is there any other solution? 

 

 

2 – ScrollTrigger:

I am using ScrollTrigger to pin and scrub some elements, for example on the "Our Services" section on the homepage. This is a very pleasing effect, but I have a problem with mobile devices... the "sticky" elements they are glitchy on scroll when used in combination with the ScrollSmoother. I've been looking into this issue for quite some time and, from what I've read here on the forum, I am probably using more than one single ScrollTrigger() to "manage" all the ScrollTrigger animations.

 

Although by not using the ScrollSmoother on mobile will fix this issue, I would like to know if somebody could have a look on the codesandbox link below and help me by showing how could I have 2 ScrollTriggers and "connect" them. This might be easy to do with `useContext()`, but I am not sure how could I use the "main ScrollTrigger" inside of another component, for instance the `TextReveal.jsx`. I had a look on the GSAP starters at StackBitz, but I couldn't really figure out how to do it.

 

 

3 – Animated background color change on scroll

Today I've updated the ScrollSoother code to use one example I saw on the starters and it seems to work fine, even when we navigate between pages. But now, the "Animated background color" effect is broken. You can find this piece of code commented on the `_app.jsx` file. I've tried to remove the `ScrollTrigger.create()` and do it in another way, with gsap.to() and gsap.fromTo(), but the effects would not be the same as `onEnter` and `onLeave`. This issue is probably happening because I am new to gsap and I don't know quite well all the available options, and how to handle them, let say.

 

Another problem raised in the meanwhile is that since I am not using the ScrollSmoother on mobile, this functionality also does not work on mobile.

 


Here is the link to the codesandbox: https://codesandbox.io/p/devbox/zc3nw5?file=%2Fsrc%2Fpages%2F_app.jsx%3A49%2C39

PS: you might need to run `npm run dev`

 

If you need any extra info or so, please just let me know and I will provide what is needed.

 

Thank you in advance,

Nuno

Link to comment
Share on other sites

Hi @OSITAKA and welcome to the GSAP Forums!

 

Thanks for being a Club GSAP member and supporting GSAP! 💚

 

The link for the demo is not working unfortunately, so we can't really have a look at it. Also the amount of files is quite large, please either reduce the demo to the bare minimum to illustrate the issue or point us directly to the files we should be looking at (also keep the amount of code in the files as small as possible).

 

By default ScrollSmoother is not applied in touch devices as mentioned in our docs:

smoothTouch
Boolean | Number - by default, ScrollSmoother will NOT apply scroll smoothing on touch-only devices (like phones) because that typically feels odd to users when it disconnects from their finger's drag position, but you can force smoothing on touch devices too by setting smoothTouch: true (same as smooth value) or specify an amount like smoothTouch: 0.1 (in seconds).

 

https://gsap.com/docs/v3/Plugins/ScrollSmoother/#config-object

 

Maybe another option could be to use normalizeScroll only in touch devices (or in a general fashion, test and see what fits best):

https://gsap.com/docs/v3/Plugins/ScrollTrigger/static.normalizeScroll()

 

8 hours ago, OSITAKA said:

Although by not using the ScrollSmoother on mobile will fix this issue, I would like to know if somebody could have a look on the codesandbox link below and help me by showing how could I have 2 ScrollTriggers and "connect" them. This might be easy to do with `useContext()`, but I am not sure how could I use the "main ScrollTrigger" inside of another component, for instance the `TextReveal.jsx`. I had a look on the GSAP starters at StackBitz, but I couldn't really figure out how to do it.

Using a context provider should be a good idea for this. How you implement it, would depend on what you're trying to achieve actually. I'd recommend you to create a small minimal demo in Stackblitz (we have far less issues with this service than with codesandbox).

 

For the background color issue, please create a minimal demo just for that in order to see it isolated.

 

Sorry for asking for minimal demos for each issue, but we don't have the time resources to comb through large and complex codebases trying to find issues and problems, less alone to go through a list of problems at the same time. Is beyond the scope of the support we provide in these free forums. That's why a single demo for each issue should be a good idea. Once we tackle the first one, we can move onto the next and so forth, but we ask for your understanding and patience since we have other questions to attend in the forums.

 

Happy Tweening!

Link to comment
Share on other sites

@Rodrigo Thank you for the reply. I understand that it's difficult to give support on large code bases. In the end, I've managed to solve some issues.

 

I still have one issue that is related to the ScrollTrigger and the gsap.matchMedia(). I have 2 elements using the ScrollTrigger on "components/Services.jsx" and right now the component has this check for the matchMedia() below, and if the user is on less than 600px wide (mobile), the ScrollTrigger would be ignored. 

 

I think I am doing something wrong on these 2 lines below. If I comment these 2 lines, the effect would work normally, but then it also would run on mobile and that's not the intention. Could you please have a look? 

let mm = gsap.matchMedia();
mm.add("(min-width: 600px)", () => {

 

I've made a new demo with only this issue. https://stackblitz.com/edit/stackblitz-starters-fpbyhx?file=app%2Flayout.jsx,app%2Fcomponents%2FServices.jsx

 

PS: I am using the ScrollSmoother on "layout.jsx".

 

Thank you

Link to comment
Share on other sites

  • Solution

Are you trying to do this?: 

https://stackblitz.com/edit/stackblitz-starters-hqtclz?file=app%2Flayout.jsx,app%2Fcomponents%2FServices.jsx

 

I noticed you weren't doing proper cleanup. 

 

You might want to consider using the brand new (not announced yet) useGSAP() hook to make it a little easier: 

https://www.npmjs.com/package/@gsap/react

Link to comment
Share on other sites

Hi @GreenSock, thank you for the reply.

 

I see you added the return () => mm.revert(); to clean up. This it works, even when I go from mobile view to desktop view and vice-verse.

Thank you!
 

 

I had a deep looking into the new useGSAP() hook. In my opinion, this will solve quite a lot of problems. I have recreated the matchMedia issue I was having using the new useGSAP() hook, but I see I am probably missing something like the mm.revert(). If we start with the browser window > 600px (scrollTrigger active), then resize to mobile viewport (scrollTrigger inactive, as expected) and finally, resize back to desktop view the ScrollTrigger will be broken.  Could you have a look on this link? https://stackblitz.com/edit/react-2prnhv?file=src%2FApp.js,src%2Findex.js.

 

Link to comment
Share on other sites

Hi,

 

Be sure to have the latest version of the useGSAP hook. It seems that you created this fork from our starter template before we updated it yesterday.

 

Finally the MatchMedia revert has to be in the return function of the useGSAP hook, not inside the MatchMedia add method:

// Bad
useGSAP(() => {
  const mm = gsap.matchMedia();
  mm.add("(breakpoint)", () => {
    return () => mm.revert();
  });
}, {
  scope: myRef
});

// Good
useGSAP(() => {
  const mm = gsap.matchMedia();
  mm.add("(breakpoint)", () => {
    // GSAP code here
  });
  return () => mm.revert();
}, {
  scope: myRef
});

This seems to work the way you intend:

useGSAP(
  () => {
    let mm = gsap.matchMedia();
    mm.add('(min-width: 600px)', () => {
      const boxes = gsap.utils.toArray('.box');
      boxes.forEach((box) => {
        gsap.to(box, {
          x: 150,
          scrollTrigger: {
            trigger: box,
            start: 'bottom 50%',
            end: 'top 20%',
            scrub: true,
            pin: true,
          },
        });
      });
      gsap.to('.test', {
        scrollTrigger: {
          trigger: '.test',
          start: 'top 30%',
          end: '+400%',
          scrub: true,
          pin: true,
        },
      });
      gsap.to('.box2-container', {
        xPercent: -100,
        scrollTrigger: {
          trigger: '.box2-container',
          start: 'top 40%',
          end: '+100%',
          scrub: true,
          pin: true,
        },
      });
    });
    return () => mm.revert();
  },
  { scope: main }
);

Hopefully this helps.

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...