Jump to content
Search Community

Issues with ScrollTrigger : animations can't keep up on fast scroll / wrong display on resize

Nelou test
Moderator Tag

Go to solution Solved by Rodrigo,

Recommended Posts

Greetings everyone,

 

I hope you have a wonderful day.

 

I came up with a couple of issues trying to make my (very first) GSAP-based website, and I'm lost at sea. I want to apologize if my method are wrongs, and I'd gladly hear from you guys if you have any advice on to how you'd tackle this puzzle.

 

First of all, I needed my sections to be pinned in place.

For this, I looped in my containers and created a scrollTrigger for each of them, and took some extra room for the end, based to the initial height of the elements (100vh). It was mainly to give some time for the next container to get pinned before the first one would go away.

 

for (let i = 0; i < containerArray.length; i++) {
  ScrollTrigger.create({
    trigger: containerArray[i],
    pin: containerArray[i],
    pinSpacing: false,
    id: "pin"+containerArray[i],
    start: 'top top',
    end: '150% top',
    markers: true
  });
}

One of my issue for this first part is, my first section is scrollable for 125% of the height of the viewport (which works as intended coded like that), but my other sections are scrollable for only 100% (because it's also how my code should work). Is there a better method to overlap sections while keeping the scrollable height identical and logical based on the height of the elements ?

 

-----------------------------------

 

Onto the next part, that's probably where I started to make many mistakes.

 

Now that I had a window in which both my current and next containers were on screen and pinned, I needed to insert a scrollTrigger between the moment the next container was pinned, and the current container was unpinned to trigger my animations.

 

So I created an other scrollTrigger for each inner section, with a start and end value of 125% (which is 25% below the moment the next container is pinned, and 25% above the current container is unpinned. Used this method mainly to ensure the animation plays after the next container is in place and before the current container goes away.)

 

For those specific scrollTriggers, and with the onLeave and onEnterBack methods, I add and remove a couple of classes, mainly to prevent sections to overlap even if they are hidden and keep allowing users to interact with the visible section (classes active / inactive) and changing the BG color of the body (to match the sections color). And after all that, I added my animation in the timeline.

 

for (let i = 0; i < sectionArray.length; i++) {           
  let tl = gsap.timeline({
    scrollTrigger: {
      trigger: sectionArray[i],
      toggleActions: "restart none reverse none",
      start: '125% top',
      end: '125% top',
      id: 'animate '+containerArray[i]+" & "+containerArray[i+1],
      markers: true,
      onLeave: () => {
        document.querySelector(containerArray[i]).classList.add("inactive");
        document.querySelector(containerArray[i]).classList.remove("active");
        if(bgColor[i+1]){
          document.querySelector("body").classList.add(bgColor[i+1]);
          document.querySelector("body").classList.remove(bgColor[i]);
          document.querySelector(containerArray[i+1]).classList.add("active");
          document.querySelector(containerArray[i+1]).classList.remove("inactive");
        }
      },
      onEnterBack: () => {
        document.querySelector(containerArray[i]).classList.add("active");
        document.querySelector(containerArray[i]).classList.remove("inactive");
        if(bgColor[i+1]){
          document.querySelector("body").classList.add(bgColor[i]);
          document.querySelector("body").classList.remove(bgColor[i+1]);
          document.querySelector(containerArray[i+1]).classList.remove("active");
          document.querySelector(containerArray[i+1]).classList.add("inactive");
        }
      }
    }
  });
  
  //Animation that should happen right in between the pin of next container,
  //and the unpin of current container
  if(containerArray[i+1] !== "undefined") {
    tl.to(sectionArray[i], {
      alpha: 0,
      duration: 0.2
    })
    tl.from(sectionArray[i+1], {
      alpha: 0,
      duration: 0.2
    })
  }
}

 

It somehow works, but only if no resize is done and if we scroll slowly.

 

When I resize, it seems to display wrong things (despite the scrollbar not moving at all since it's mainly opening the console and resizing horizontally?) and I have no idea how to resolve that.

 

When I scroll too fast, the same thing happens. But I thing I know where it comes from. Probably from the fact each section has a scrollTrigger bound to said section, and the one after it (called with [i] and [i+1]), which means triggering multiple scrollTrigger at the same time basically asks for the same section to be animated "to" alpha 0 and "from" alpha 0 at the same time, but I have no idea how to fix that...


image.thumb.png.931921186144b4d0414057e01382a3f4.png

 

I also can't seem to prevent the last scrollTrigger to appear, but that's probably just me being too deep into it that I can't find the solution that is right under my nose, haha !

 

image.thumb.png.5326059f66695bb3514a03213b1fb2b5.png

 

I hope my code isn't a mess, I hope I've been clear enough for you to be able to give me some guidance.

 

Thanks for reading, and have a good day !

 

Nelou.

See the Pen Exedrzw by Nel-Nelou (@Nel-Nelou) on CodePen

Link to comment
Share on other sites

  • Solution

Hi @Nelou and welcome to the GreenSock forums!

 

You can use preventOverlaps in your ScrollTrigger configuration:

for (let i = 0; i < sectionArray.length; i++) {           
  let tl = gsap.timeline({
    scrollTrigger: {
      trigger: sectionArray[i],
      toggleActions: "restart none reverse none",
      start: '125% top',
      end: '125% top',
      preventOverlaps: true, // <- HERE
      id: 'animate '+containerArray[i]+" & "+containerArray[i+1],
      markers: true,
    }
  });
}

You can read more about it here:

https://greensock.com/3-8#preventOverlapsAndFastScrollEnd

 

Be sure to watch @Carl's great video, which explains in details how it works.

 

On top of that, right now you have a very convoluted setup. Since every section has only one child element, why are you running two loops? This could be simplified quite a bit by running just one loop and selecting the child element of each parent section. Also I'd try to create just a single ScrollTrigger instance for each section and run the animation on that.

 

As for the resize event issue, it seems that the order you're creating the ScrollTrigger instances is what's causing those problems. I couldn't tell you exactly why, but creating the parent containers ScrollTriggers after the other ones seems to resolve the issue. Is a bit odd since the parent element is being pinned but without pin spacing, so that shouldn't mess the calculations ScrollTrigger makes for the other instances, but apparently it does, so this seems to work:

// Run child sections loop first
for (let i = 0; i < sectionArray.length; i++) {
}

// Run parent sections loop after
for (let i = 0; i < containerArray.length; i++) {
}

 

Hopefully this helps.

Happy Tweening!

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

Hello Rodrigo,

 

It solved my many problems, thanks a lot !

 

Quote

On top of that, right now you have a very convoluted setup. Since every section has only one child element, why are you running two loops? This could be simplified quite a bit by running just one loop and selecting the child element of each parent section. Also I'd try to create just a single ScrollTrigger instance for each section and run the animation on that.

 

I tried that in a previous version, but oddly enough, they were not synchronized the way I wanted. But if you tell me it's possible I'll give it an other shot !

 

Once again thank you so much for your reply. Have a fantastic day

 

😄

  • Like 1
Link to comment
Share on other sites

  • 11 months later...
On 3/22/2023 at 7:23 PM, Nelou said:

Hello Rodrigo,

 

It solved my many problems, thanks a lot !

 

 

I tried that in a previous version, but oddly enough, they were not synchronized the way I wanted. But if you tell me it's possible I'll give it an other shot !

 

Once again thank you so much for your reply. Have a fantastic day

 

😄

Hello! 
 

can you post final results with solved problems?

Link to comment
Share on other sites

13 minutes ago, Rodrigo said:

Hi @Lenspre,

 

If you're having issues, you can create a minimal demo that illustrates the issues you're having so we can take a look and we'll be more than happy to help you through any GSAP related issues you could have.

 

Happy Tweening!

Already posted and need help ;)

 

 

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