Jump to content
Search Community

Multiple scrollTriggers in multiple .each-functions (jQuery)

akapowl test
Moderator Tag

Recommended Posts

Hey there,

 

I am applying multiple ScrollTriggers to multiple sections via multiple .each-functions (jQuery).

 

 

When only having one .each-function, everything works just fine and as expected with either one of those two in my pen. 

Elements get pinned, when they should and animations run as intended.

 

As soon as I have multiple .each-functions though, things start to get all wonky - pinned elements start being animated when they are not supposed to - way to early. It seems like everything is out of place.

 

Am I doing something horribly wrong here?

Would be glad if somebody could point me in the right direction.

 

Cheers,

Paul

 

See the Pen 2feab8db2006bd6440047302f03e455f by akapowl (@akapowl) on CodePen

Link to comment
Share on other sites

You're right. Sorry, there's a fair bit to parse through and I didn't check explicitly.

 

I believe that the issue here is that you create a bunch of ScrollTriggers with pinning and then create a bunch more triggers with pinning. It looks like the ones originally created don't accommodate for the extra space added by the later ones. Maybe @GreenSock can check me there if I'm wrong. AFAIK this shouldn't be an issue so we'll take a deeper look to see exactly what's happening.

 

You should also make sure to set functional values for things that will change on resize. I did that in this pen (the issue still exists):

See the Pen WNryEXp?editors=0010 by GreenSock (@GreenSock) on CodePen

  • Like 1
Link to comment
Share on other sites

29 minutes ago, ZachSaucier said:

You're right. Sorry, there's a fair bit to parse through and I didn't check explicitly.

 

Nah, I am sorry for the large amounts of code to look through. Thanks for your effort on that part.

 

 

30 minutes ago, ZachSaucier said:

It looks like the ones originally created don't accommodate for the extra space added by the later ones. 

 

Something like that was what I thought initially - that might be the reason why the different instances somewhat overlap.

But I really am no expert when it comes to JavaScript/jQuery, so I always consider a mistake on my behalf first.

 

 

33 minutes ago, ZachSaucier said:

You should also make sure to set functional values for things that will change on resize.

 

And thanks a lot for pointing that out - would have been the next step to work on anyway.

 

Link to comment
Share on other sites

The problem is that (particularly with pinning) you should create your ScrollTriggers in the order they'd take effect. Your code is jumping around on the page. So you're creating a ScrollTrigger that's further down on the page FIRST, and then later you're creating a ScrollTrigger that's ABOVE that one which would push it down. It's very hard for ScrollTrigger to know your page layout and handle all of that automatically. However, this helper function should do a decent job in most cases: 

function orderTriggers() {
  let triggers = ScrollTrigger.getAll();
  triggers.sort((a, b) => a.start - b.start);
  triggers.forEach(trigger => {
    trigger.kill();
    ScrollTrigger.create(trigger.vars);
  });
  ScrollTrigger.refresh();
}
orderTriggers();

You'd run that function AFTER you've created all of your ScrollTriggers. Seems to work okay in your demo, right? 

 

This is a pretty rare edge case because most people intuitively create their ScrollTriggers in the proper order. 

 

Does that clear things up? 

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

@GreenSock That helper function indeed does the trick with my initial pen posted here, thanks.

 

But when I turn to setting functional values for things that will change on resize, just as @ZachSaucier hinted me to do above, it doesn't seem to work.

The pins are working just fine and as expected, but the selected elements are not being animated anymore.

 

See the Pen 565970116f5aee6bd5acf58a89261080 by akapowl (@akapowl) on CodePen

 

Why could that be? I just couldn't figure it out over the weekend.

  • Thanks 1
Link to comment
Share on other sites

That actually had to do with the invalidateOnRefresh: true that you added, and a regression/bug that was introduced in 3.4.0. I've updated the next release which you can preview at: 

core: https://assets.codepen.io/16327/gsap-latest-beta.min.js

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

 

That updated ScrollTrigger should also allow you to omit that helper function that does the reordering (though it won't hurt anything). 

 

Better? 

  • Like 2
Link to comment
Share on other sites

Alright, yes, that works a lot better.

Animations are back and resizing works properly.

 

Just one thing I noticed (although you might already know that and be working on it since this is still beta):

 

I have a ScrollTrigger for a Scroll-Progress-Bar that takes into account the whole height of the document.

Animation on that works just fine, so I left it out in the pen.

But it is dependent on the progress value and I noticed that that value is offset now.

To say it with Zach's words: it looks like it doesn't accomodate for the extra space added by the pins.

 

You can see that if you check the console for this pen:

See the Pen c0ad7ecfa73edf600bc2a1172ee38ce6 by akapowl (@akapowl) on CodePen

 

Somewhere around the middle in that pen, the extra ScrollTrigger I added reaches its progress of 1, which it should on the bottom of the page, if I didn't make a mistake there.

 

Anyways, thanks once mor for all the helping.  

 

Link to comment
Share on other sites

Ah, that's the conundrum. Let me explain the context...

 

When ScrollTrigger does a refresh, it must revert everything so that nothing is pinned, no extra padding is added, etc., so that those things don't interfere. It must go in some order and build things up and do measurements. So if we order things by where the "start" values are, think about where your overall page ScrollTrigger would be (the one that's handling the progress bar) - it'd be the very FIRST one in the list. So when it does its measurements, nothing is pinned, no extra spacing is added, etc. - that's why the "end" value seems too early. That's where the end of the page was at the time of those measurements...but then later there were pins that were added, extra pinSpacing, etc. 

 

It's not feasible to keep bouncing back up and down and locking in the measurements and then going backwards and re-measuring things for the prior ones, etc. 

 

So in a way, we're back where we started - it's almost always best to trust the user to build things in the order they'd happen on the page. In your case, your intuition to put that overall page progress one LAST was correct. But when I added the auto-sorting internally based on the "start" values, that went from being calculated last to being calculated first. 

 

See the issue? 

 

One solution I can see is to let people optionally define a "priority" value (a number) that tells ScrollTrigger how to prioritize things generally when sorting that list. In this case, since you want the overall page progress one to go last, you could set priority: -1 because 0 is the default. In other words, that's like saying "do this one after all the regularly-prioritized ones". 

 

The only other decision to make for ScrollTrigger is whether or not we automatically sort the list of triggers by their "start" values (as I'm doing in 3.4.1 now) -OR- we could skip that and provide a method like ScrollTrigger.sort() you'd have to manually call if you need it. The up side to doing it automatically is that in most cases, it'll probably work pretty well but like in your scenario here it could be confusing if someone builds things in the order they'd happen on the page and then it doesn't work the way they'd expect (since things got re-ordered by "start" instead of honoring the order the user created them). 

 

I think in general people will intuitively build things  in the order they happen, so doing the auto-sort internally may cause more problems than it solves. Curious what others think. 

  • Like 3
Link to comment
Share on other sites

11 hours ago, GreenSock said:

I think in general people will intuitively build things  in the order they happen, so doing the auto-sort internally may cause more problems than it solves. Curious what others think. 

I'd avoid auto sorting as it doesn't work across the board and adds more complexity. I'd be in more favor of a sorting property than auto sorting but at the moment I think just having people create them in the order needed is sufficient.

  • Like 2
Link to comment
Share on other sites

 

12 hours ago, GreenSock said:

See the issue? 

 

Ah, okay, I see the problem there.
And I think you're right, sorting the triggers internaly, like you would in 3.4.1, might cause too much confusion for users (just like it did for me there).

 

Your solution with providing a sorting method, that can be called manually when needed, in combination with setting up priority-values definitely sounds good to me. That way you'd keep it intuitive for basic use, but let users have the option to tweak it for more edgy cases, if needed.

 

  • Like 1
Link to comment
Share on other sites

Agreed. The latest beta removes the auto-sorting and adds a ScrollTrigger.sort() method. By default, it'll sort by "start" values AND any "priority" that you set on each ScrollTrigger (optional). Or you can pass your own custom sorting function to the method. Cool? 

  • Like 1
  • 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...