Jump to content
Search Community

ScrollTrigger seem to fail randomly + other issues

xperator test
Moderator Tag

Recommended Posts

Hey, First of all thanks for your great work with this great tool!

I'm gonna try to keep it short so bear with me if this ends up a long post. So my dev stack is Vue + Vite + Inertia + Laravel and I've used gsap here and there in few projects and I never had any issues with it so far 👍.

But I just started working on a new demo website for a client where I'm using gsap almost everywhere.

And the problem is I'm seeing some weird behavior which I can summarize in 2 points:

  • Some animations that are supposed to start by ScrollTrigger, won't work. This happens only sometimes and it happens randomly and I cant pinpoint it to an exact component. For instance an element that has initial opacity of 0 and should change to opacity of 100 when it's in the viewport, it does not work. Sometimes this throws an error saying Cannot read properties of undefined (reading 'pin') and sometimes it doesn't even throw this error. But here is how the error looks like :gsap-scrolltrigger-error.png.abc1cfad387058124e3b8549a454379b.pngAnd below image is the code relatedgsap-scrolltrigger-error-code.png.d0799d6b878c33911a33e9af84db3d50.png
  •  Some timeline animations act weirdly when I navigate away from the page and come back to it. Like after the initial playback, when you navigate to a different page and go back to try to see the component with the timeline animation again, it start from a certain point of the timeline as if it was cached somewhere, I even noticed some of the element styles from the first playback are still applied ( Even though I double checked the DOM element does not exist when I navigate to a different page, and I also checked Vue Devtools to make sure the component isn't there either. But still somehow )

 

I'm not sure why these problems are happening. Maybe it's my "heavy" usage of GSAP, which I doubt because I'm sure there are tons of websites out there that totally surpass my usage and are probably doing fine. Or maybe the problem is that GSAP does not play well with SPA apps. Or maybe It's my code.

 

I know you're gonna ask for a replicate demo so you can look into, but trust me I cannot even replicate the problem myself because it happens randomly under unknown circumstances. Also I have a custom setup which I think will be a hell of a job to duplicate in an online code sandbox tool.

But I can DM you the URL of the demo that I'm working on ( sorry can't share it here for privacy reasons )

 

Here are the things that I've tried :

  1. I've tried adding gsap to the optimizeDeps.include of my vite.config.ts file
  2. I've tried killing the gsap timeline instance during component unmount
    onBeforeUnmount(() => {
      productsTimeline?.clear()
      productsTimeline?.kill()
      productsTimeline = null
    })
  3. I've tried different combinations of to , fromto and from but no luck
  4. I've tried using ScrollTrigger.refresh() in places where I thought there should be one, like after initializing a Swiper instance :
    products_swiper.value = new Swiper('#products-swiper', {
      on: {
         init: () => {
            ScrollTrigger.refresh()
         }
      }
    }
  5. A bunch of other things I don't quite remember ( like using an id on ScrollTrigger, etc... )

 

And this would be an example how I use gsap in my Vue components :

import { gsap, ScrollTrigger } from '@/js/utils/gsap'

onMounted(() => {
  gsap.fromTo('#why-section .gsap-why-title', {
        scale: 1.2,
        autoAlpha: 0,
    }, {
        scrollTrigger: {
            trigger: '#why-section .gsap-why-title',
            once: true,
            start: 'top center+=300px',
            end: 'bottom bottom',
        },
        scale: 1,
        autoAlpha: 1,
        duration: 1,
        ease: 'power3.out',
        delay: 0.5,
    })
})


// And in my '@/js/utils/gsap' file I have :

import gsap from 'gsap'
import ScrollTrigger from 'gsap/ScrollTrigger'
gsap.registerPlugin(ScrollTrigger)

export { gsap, ScrollTrigger }

 

Any ideas ?

Thanks in advance!

Link to comment
Share on other sites

Welcome to the forums @xperator

 

2 hours ago, xperator said:

I know you're gonna ask for a replicate demo so you can look into... But I can DM you the URL of the demo that I'm working on ( sorry can't share it here for privacy reasons )

 

Yep, we definitely like to have something we can see first hand and experiment with so having the URL to live site probably wouldn't me of much use. 

 

2 hours ago, xperator said:

I'm not sure why these problems are happening. Maybe it's my "heavy" usage of GSAP, which I doubt because I'm sure there are tons of websites out there that totally surpass my usage and are probably doing fine. Or maybe the problem is that GSAP does not play well with SPA apps. Or maybe It's my code.

 

Heavy usage wouldn't be an issue and GSAP plays nicely with SPAs as long as you work within its constraints and lifecycles, e.g. creating animations after the element has been rendered, using refs, killing ScrollTriggers on route changes, etc.

 

Ex: killing all ScrollTriggers.

ScrollTrigger.getAll().forEach(t => t.kill());

 

2 hours ago, xperator said:

Sometimes this throws an error saying Cannot read properties of undefined (reading 'pin') and sometimes it doesn't even throw this error. But here is how the error

 

Are you pinning stuff? If you are, make sure you are not to pin the to root element in a component. 

 

<template>
  <!-- dont' pin me -->
  <div>
    <!-- pin me instead -->
    <div></div> 
  </div>
</template>

 

2 hours ago, xperator said:

For instance an element that has initial opacity of 0 and should change to opacity of 100 when it's in the viewport

 

There is a known regression, so you can try adding lazy: false to your animations.

 

 

There was another issue with using once, but I'm not sure if it's related to your issue.

 

 

2 hours ago, xperator said:

Some timeline animations act weirdly when I navigate away from the page and come back to it. Like after the initial playback, when you navigate to a different page and go back to try to see the component with the timeline animation again, it start from a certain point of the timeline as if it was cached somewhere, I even noticed some of the element styles from the first playback are still applied ( Even though I double checked the DOM element does not exist when I navigate to a different page, and I also checked Vue Devtools to make sure the component isn't there either. But still somehow )

 

Make sure you are killing your ScrollTriggers when the route changes, and if you have a transition on your router, onMounted is going to fire before the page is ready, throwing your ScrollTriggers off.

 

I would also try to rule other stuff that might be conflicting, like maybe that Swiper thing you are using.

 

  • Like 1
Link to comment
Share on other sites

@OSUblake Thank you for your welcome 😊 and thanks for your great and detailed response!

  1. Killing all the ScrollTrigger on route change will cause every animation that relies on ScrollTrigger to fail to start.
    // Navbar component ( which is a persistent component )
    onMounted(() => {
        Inertia.on('navigate', (event) => {
            ScrollTrigger.getAll().forEach(t => t.kill())
        })
    })

     

  2. I'm not pinning anything in any place that's why I'm confused on why the error is pointing to the `pin` method.
  3. So do I need to apply lazy: false to every place where I have from() and opacity ? Does this also affect autoAlpha as well ?
  4. I will try to remove once: true from every ScrollTrigger and see how it goes.

Btw I read this comment on StackOverflow regarding the "Vue-Router and Gsap ScrollTrigger" topic, and I wonder how much of this is true ?

Quote

This is the problem when you have components from previous page AND the next page at the same time, and ScrollTrigger calculates the values (offsetTop) in that time

 

Update :

I tried adding lazy: false and also removed all once: true and the problem still persist.

Link to comment
Share on other sites

2 hours ago, xperator said:

Btw I read this comment on StackOverflow regarding the "Vue-Router and Gsap ScrollTrigger" topic, and I wonder how much of this is true ?

 

Do you have a link to that? I'm not exactly sure as to what that statement is referring to.

 

2 hours ago, xperator said:

Killing all the ScrollTrigger on route change will cause every animation that relies on ScrollTrigger to fail to start.

// Navbar component ( which is a persistent component )
onMounted(() => {
    Inertia.on('navigate', (event) => {
        ScrollTrigger.getAll().forEach(t => t.kill())
    })
})

 

 

 

Then you need to get the kill the relevant ones. You could still use getAll and then filter out the ones that should be killed based on their ID, or use getById to kill the ones that need to be killed. Or just keep a reference to the ones that should be killed.

 

let tween = gsap.to(".foo", {
  x: 100,
  scrollTrigger: {}
});


// kill
tween.scrollTrigger.kill();

 

2 hours ago, xperator said:

So do I need to apply lazy: false to every place where I have from() and opacity ? Does this also affect autoAlpha as well ?

 

On every from animation. Doesn't matter what they are animating.

 

2 hours ago, xperator said:

I'm not pinning anything in any place that's why I'm confused on why the error is pointing to the `pin` method.

 

There shouldn't be any errors for that if you aren't pinning. 🤷‍♂️

 

Can you try the beta files to see if that might fix your issues.

 

You'll need the latest GSAP and ScrollTrigger.

https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/gsap-latest-beta.min.js

https://assets.codepen.io/16327/ScrollTrigger.min.js

 

 

  • Like 1
Link to comment
Share on other sites

11 hours ago, OSUblake said:

Thanks for the beta version links but I'm not entirely sure how to import them since I'm using the esm method to import them: 

import gsap from 'gsap'
import ScrollTrigger from 'gsap/ScrollTrigger'
gsap.registerPlugin(ScrollTrigger)

 

11 hours ago, OSUblake said:

Do you have a link to that? I'm not exactly sure as to what that statement is referring to.

Here is the link. The OP also seem to use similar setup and have the issue where ScrollTrigger does not trigger when navigating to different pages.

 

11 hours ago, OSUblake said:

Then you need to get the kill the relevant ones. You could still use getAll and then filter out the ones that should be killed based on their ID, or use getById to kill the ones that need to be killed. Or just keep a reference to the ones that should be killed.

I've tried killing them by id, and also per page. It doesn't work.

 

11 hours ago, OSUblake said:

On every from animation. Doesn't matter what they are animating.

As I mentioned in my previous post "update", adding lazy: false to every from and also removing all once: true doesn't fix the issue.

 

11 hours ago, OSUblake said:

There shouldn't be any errors for that if you aren't pinning. 🤷‍♂️

Then that could be an internal gsap issue that happens under certain circumstances.

Link to comment
Share on other sites

14 minutes ago, xperator said:

Thanks for the beta version links but I'm not entirely sure how to import them since I'm using the esm method to import them: 

 

They are UMD files, so you should be able to import it any environment that allows CommonJS. If not, you can use <script> tags.

 

import { gsap } from "../some-directory/gsap-latest-beta.min.js"

 

24 minutes ago, xperator said:

Here is the link. The OP also seem to use similar setup and have the issue where ScrollTrigger does not trigger when navigating to different pages.

 

That sounds like what I mentioned earlier, especially the post below the OP. Nuxt automatically creates a transition, so ScrollTriggers created in onMounted are going to be created at the wrong time.

 

15 hours ago, OSUblake said:

Make sure you are killing your ScrollTriggers when the route changes, and if you have a transition on your router, onMounted is going to fire before the page is ready, throwing your ScrollTriggers off.

 

26 minutes ago, xperator said:

Then that could be an internal gsap issue that happens under certain circumstances.

 

That shouldn't happen if there are no pins in your code, but I would try those beta files first as there's a bunch of bug fixes in them, so hopefully whatever you're experiencing has already been fixed. 

 

  • Like 1
Link to comment
Share on other sites

Hey @OSUblake,

I've tried the beta version and I can confirm only the `from` opacity issue still exist, I'm not 100% sure about the ScrollTrigger issue because I still haven't managed a way to replicate the situation where the error happens. But I did not encounter that one when testing the current beta.

 

Thank you very much for sticking with me on this matter even though I provided no demo to work with. At least now I have some clues.

 

Since this seem to be more specific to ScrollTrigger not playing well in my SPA environment, and also I'm guessing some possible other internal issues are happening with GSAP, so I'm gonna try few things (workarounds) :

  • I've replaced all my from() to fromTo()` and the opacity issues are gone 
  • I've replaced all my ScrollTrigger with a manual Intersection Observer to start the animations which works now 

Although obviously this is not an optimal solution and this means more code + lack of ScrollTrigger plugin convenience and features, but at least the animations themselves will work.

Not to mention I've spent too much time on this subject (almost a week). I seriously lost hope on the usage of GSAP plus the fact there no active libraries/tools out there that are powerful as GSAP. I even went out of my way during these past few days to try to rewrite the app in a React ecosystem so I could use Framer Motion and possibly have better time with the animations. But that fall short quickly for many reasons.

Link to comment
Share on other sites

7 hours ago, xperator said:

I've replaced all my from() to fromTo()` and the opacity issues are gone 

 

Is it just opacity that isn't working? In the code you posted at the top, you also had scale, so only the scale was working? And can you see any of the inline styles being changed?

 

When an opacity from animation fails, that usually means it's being created multiple times very quickly, like in this demo from the Most Common GSAP Mistakes. If you press restart quickly, it will never reach an opacity of 1.

 

See the Pen gOPXLwN by GreenSock (@GreenSock) on CodePen

 

I'm wondering if you might be creating from animations on an element that previously had a from animation on it but it never completed.

 

7 hours ago, xperator said:

I've replaced all my ScrollTrigger with a manual Intersection Observer to start the animations which works now 

 

When you had it with ScrollTrigger, were the markers in the correct place, and could you fire off callbacks like onEnter and onLeaveBack?

 

If this are truly GSAP bugs, we obviously want to get to the bottom of and make sure it's fixed for the next release, but it's nearly impossible to do that if we can't reproduce the issue. I know it's easy to blame GSAP if something doesn't work, but GSAP doesn't run or control any part of a framework like Vue. As long everything in the DOM is correct when you create an animation/ScrollTrigger, it should just work sans the bugs I've listed above.

 

But again, we definitely want to fix any issues so if you can provide any more clues as to how to reproduce the issue we'd definitely appreciate it. 

 

Would it possible to even look at your repo? You can just DM me for privacy. 

 

Link to comment
Share on other sites

  • 3 months later...

Hi @xperator.  @OSUblake isn't ignoring you - it has just been impossible for him to tend to the forums (long story - he can explain when he's back if he chooses to). 

 

If you need help, please provide a minimal demo that clearly isolates and illustrates the issue and we'd be happy to take a peek. Just some colored <div> elements - don't include your whole project because that's beyond the scope of help we can provide here (the issue could be CSS, a 3rd party library, a framework, markup issues - there are sooo many factors in a live site that make it complicated to troubleshoot). 

 

But again, if it's a GSAP-specific question we can help with, we'd love to. Once we see that minimal demo (like a CodePen or CodeSandbox), I'm sure it'll become more clear.

 

By the way, you're not using React, are you? Because React 18 introduced some very odd behavior that affects .from() tweens (not a bug in GSAP at all - it's a logic issue due to the fact that React 18 calls useEffect() twice instead of once in strict mode). I can explain more if you are indeed using React, but your original posts indicated you're using Vue. 

  • Like 1
Link to comment
Share on other sites

Hey @GreenSock
Thanks for the reply. I'm actually in no rush by any means. As I've already deployed the project that I was working on when I reported the issue and I've used different solutions to get around it (such as using Intersection Observer api directly instead of ScrollTrigger).

As for the demo, I've already provided @OSUblake one which he managed to run and reproduce the issue as far as I remember ( we talked in DM back then ). Unfortunately I don't have enough time at the moment to produce another demo. So excuse me for that.

 

The reason I revived this few months old topic was solely because I was curious if there was any updates in regards to this issue ( or just any fixes/updates on the ScrollTrigger since then )

Either way thanks for your great work! 

Link to comment
Share on other sites

That's why forums are great, anyone can pick up where others left off. If code is walled off in repo's risks the fact that any one person could take some time off and be of the forum for a while.

 

Repo links are fine, but can take some time to set up for someone to get up and running, that's where minimal demos come in! They take no setup for the one helping out, so you increase your chances of getting good and timely help.

 

Again any one person can take time off, but with all the great helpers around here there is always someone willing to spare some time to help out. The only thing you'll need to do is give them the tools to do so.
 

Speaking off... I'm of for some well earned vacation! Good luck!

 

  • Like 2
Link to comment
Share on other sites

8 hours ago, xperator said:

The reason I revived this few months old topic was solely because I was curious if there was any updates in regards to this issue ( or just any fixes/updates on the ScrollTrigger since then )

Absolutely, we've been hard at work on a bunch of things in ScrollTrigger, ScrollSmoother, and the GSAP core. Hundreds of hours invested. And if I understand your original post correctly, yes, it's very likely that it's already fixed in the upcoming release. If you'd like to try the beta version I can hook you up with that.

 

8 hours ago, xperator said:

Either way thanks for your great work! 

Absolutely! 🙌

 

7 hours ago, mvaneijgen said:

Speaking of... I'm off for some well earned vacation! Good luck!

Enjoy, @mvaneijgen

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