Jump to content
Search Community

How to reinitialise a Tween?

JDansercoer test
Moderator Tag

Recommended Posts

Hey guys,

 

I'm currently developing a Next.js project that heavily uses gsap. 

 

However, I'm facing an issue with a component that is used across multiple pages, but its animation does not get fixed on page switches.

When you are at the homepage, and scroll all the way down, you'll see that the footer animates in as as it should. However, when you switch pages, the footer will never be visible, because of course it never reaches that point.

 

I tried playing around with `.kill()` function (see the commented out code), but that does not seem to solve the issue.

 

You can find my sandbox at https://codesandbox.io/s/naughty-ride-vh1e6?file=/src/Footer.js

 

How can this be fixed?

Link to comment
Share on other sites

Perhaps the only thing not-react-way is the cleanup effect being run at the start of the hook and not in the cleanup function, but besides that Zach's solution is spot on, because He is using a ref to store the GSAP instance so is kept in subsequent re-renders. Then in order to avoid any possible conflicts He creates a new GSAP instance when the component is re-rendered because since the scroll height of each route is different the ScrollTrigger animation might won't happen. Finally He's using a fromTo() instance instead of a from() instance, because you could have issues with GSAP taking the element from opacity: 0 to opacity: 0 which will result in nothing being visible, while the fromTo() instance ensures the start and end value of the GSAP target.

 

If you move the kill() method to the cleanup function in the useEffect hook, it works as expected as well.

 

Finally, maybe you have a different approach that is more suited to your project's need and Zach's doesn't fit into that. If you share that we could get something working for sure.

 

Happy Tweening!!!

  • Like 2
Link to comment
Share on other sites

Hey @Rodrigo,

 

Thanks a bunch for pointing me in the right direction. 

 

In my original post, I already stated that I had tried working with using .kill() in the cleanup effect, but that that seemed to do nothing.

 

  useEffect(() => {
    animation.current = gsap.from(wrapper.current, {
      opacity: 0,
      scrollTrigger: {
        trigger: wrapper.current,
        scrub: true,
        end: "+=100%"
      }
    });

    return () => {
      animation.current.kill();
    };
  }, [location.pathname]);

However, upon further inspection and thanks to your remarks, I found out that indeed the animation was being killed of, as it should be. But the key issue was that my original attempt did not have a fromTo(), but only a from(). What I think was happening was that, upon switching page, gsap would start a new animation and check it's current state. But because that probably had opacity: 0 (since it was not in the viewport), it would animate from opacity to opacity 0 (which was the state it probably last knew.

 

So combining this with my previous remark about cleanup effects, gave me the code below, which appears to work 100%.

 

  useEffect(() => {
    animation.current = gsap.fromTo(
      wrapper.current,
      {
        opacity: 0
      },
      {
        opacity: 1,
        scrollTrigger: {
          trigger: wrapper.current,
          scrub: true,
          end: "+=100%"
        }
      }
    );

    return () => {
      animation.current.kill();
    };
  }, [location.pathname]);

Thanks!

  • Like 1
Link to comment
Share on other sites

  • 5 weeks later...

Hi @Rodrigo and @ZachSaucier,

 

Sorry for coming back to this topic so late, but I just tried implementing the solution I proposed above, but it turns out that this does NOT solve my original issue.

 

Open the first CodeSandbox with a solution made by @ZachSaucier, and follow the next few steps:

  • Start on the homepage.
  • Scroll down, you correctly see the element fading into view.
  • Navigate to another page.
  • Scroll down, again you have expected behavior.
  • Now go back to the homepage, but highlight the animating element in your inspector. When you're at 33% or 66% of the page (depending on what page you navigated to in step 3), you'll notice that the element (that is currently not in view), will start animating. 

So this goes to show that the .kill() function is not being executed for some reason, or that the Tween is not being garbage collected. Any idea?

Link to comment
Share on other sites

That appears to do the trick!

Didn't know the ScrollTrigger had it's own life and is not killed when killing a Tween.

 

Below, for anyone interested, is the solution with a cleanup.

 

  useEffect(() => {
    animation.current = gsap.fromTo(
      wrapper.current,
      {
        opacity: 0
      },
      {
        opacity: 1,
        scrollTrigger: {
          trigger: wrapper.current,
          scrub: true,
          end: "+=100%"
        }
      }
    );

    return () => {
      animation.current.scrollTrigger.kill();
      animation.current.kill();
    };
  }, [location.pathname]);

 

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