Jump to content
Search Community

Scrolltrigger doesn't recalculate start/end positions and values when window is resized with react-three-fiber model animation

nkrs test
Moderator Tag

Go to solution Solved by Rodrigo,

Recommended Posts

Hi. I've been stuck on this issue for 3 days now. I went through all the docs, StackOverflow answers, gsap docs, codepens, gpt 4 answers etc, but I still can't figure out what is going wrong with my component. Maybe I'm just too stupid.

Anyway. Here's the codesandbox (took me hours to figure out how to do this without bringing all the code and an entire nextjs app, so i just copied the styles and recreated the important components)

https://codesandbox.io/s/lingering-pine-rkgr79?file=/src/components/FrontPageScene.tsx

Unfortunately, i didn't use codepen.

 

The animation should work as such: brain model moves left, then stays there for the entirety of the pinned element, then goes right when the footer appears. This works, but if you resize the window (not even fully to mobile) you'll notice that it starts to break and it doesn't recover.

On mobile it should rotate the model, which doesn't work at all, but I'm guessing that's a threejs issue i also am trying to figure out....

 

It looks like when I resize, the pinned component "height" is completely ignored in the scrolltrigger calculations afterward.

 

Any help would be super appreciated and i apologize if somehow i made dumb mistakes.

Link to comment
Share on other sites

  • nkrs changed the title to Scrolltrigger doesn't recalculate start/end positions and values when window is resized with react-three-fiber model animation

Hi @nkrs and welcome to the GSAP forums!

 

There are a few things  to notice, first this:

useEffect(() => {
  window.addEventListener("resize", onResize);
}, []);

// cleanup
useLayoutEffect(
  () => () => {
    window.removeEventListener("resize", onResize);
  },
  []
);

That is quite a redundancy, there is no need to attach an event listener in an effect hook and remove it on another effect hook, it can all be done in just one:

useEffect(() => {
  window.addEventListener("resize", onResize);
  return () => window.removeEventListener("resize", onResize);
}, []);

That's cleaner, easier to follow and does exactly the same.

 

Then you have this:

useIsomorphicLayoutEffect(() => {
  const ctx = gsap.context(() => {
    if (!brainRef.current) return;

    if (isDesktop) {
      // GSAP Code Here
    } else {
      // GSAP Code Here
    }
  });

  return () => ctx.revert();
}, []);

That effect hook has an empty dependencies array, so basically it runs one time during the lifecycle of your component. So basically the GSAP code executed in your GSAP Context instance will be one or the other and when the screen resizes and the breakpoint is passed, the other part of the code won't be executed. So if you have a screen wider than 1000 px and then resize it to be less than 1000 px, the GSAP instance will be the same.

 

You should look into GSAP MatchMedia:

https://gsap.com/docs/v3/GSAP/gsap.matchMedia()

 

GSAP MatchMedia is a wrapper for GSAP Context with responsive super powers, so it does everything GSAP Context can with the extra responsive capabilities,  so the code in the isomorphic effect hook would look like this:

useIsomorphicLayoutEffect(() => {
  if (!brainRef.current) return;
  
  const mm = gsap.matchMedia();
  
  mm.add("(max-width: 1000px)", () => {
    // GSAP Code for small screen
  });
  mm.add("(min-width: 1001px)", () => {
    // GSAP Code for large screen
  });
  return () => mm.revert();
}, []);

Porting your demo would look something like this:

https://codesandbox.io/s/festive-rgb-5w6wcm

 

Hopefully this helps.

Happy Tweening!

Link to comment
Share on other sites

18 minutes ago, Rodrigo said:

Ahh... sorry it was set as private. It's public now so you can see and fork it.

 

Happy Tweening!

Ok thank you i have applied the suggestions and I think I actually just missed the variable in the dependency array of the useEffect only on the codesandbox, because locally I had it and it still worked. Anyway, I used gsap.watchMedia but the root issue persists. If I resize the window the layout breaks and I need to refresh it to bring it back to normal... I can reproduce it in your forked codesandbox as well... I just can't understand why this happens...

Link to comment
Share on other sites

  • Solution

Hi,

 

I didn't looked into other files but you're not cleaning up in your Showcase.tsx file. You have two effect hooks there and you're not using GSAP Context/MatchMedia in one of them. That definitely can cause issues.

 

When working with React always use GSAP Context/MatchMedia in order to do proper animation cleanup, which is even more important when it comes to ScrollTrigger.

 

Happy Tweening!

Link to comment
Share on other sites

13 hours ago, Rodrigo said:

I didn't looked into other files but you're not cleaning up in your Showcase.tsx file. You have two effect hooks there and you're not using GSAP Context/MatchMedia in one of them. That definitely can cause issues.

 

When working with React always use GSAP Context/MatchMedia in order to do proper animation cleanup, which is even more important when it comes to ScrollTrigger.

 

Oh wow, thank you so much. That was indeed the issue and I completely missed the cleanup there.  I've updated my original codesandbox with the corrected code in case anyone will find it useful.

 

Edit: actually, I was being too optimistic too early. Apparently it fixes it for the most part, but the position and rotation still seem to bug out in some way when switching from mobile to desktop and vice-versa (e.g, sometimes it's too much to the left or the rotation isn't complete).

Link to comment
Share on other sites

Hi,

 

Can  you point us directly to the file that is not working/behaving the way it should? Unfortunately we don't have the time resources to comb through several files with hundreds of lines of code trying to find out where the problem is.

 

Also did you tried your app without GSAP in order to see that the layout is working as expected without GSAP/ScrollTrigger?

 

Finally be 100% sure to use GSAP MatchMedia in your other React component since it seems you have the same setup using an isDesktop boolean and two different effect hooks that depend on a common dependency. That spells trouble to me and is a React related thing, not a GSAP related one.

 

Happy Tweening!

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