Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
nvatland

ScrollTrigger.refresh() Help

Recommended Posts

Hello!

 

First of all, I must say that I am absolutely loving ScrollTrigger, thank you so much!

 

I have a div that pins to the top right portion of my page when it reaches the top and stays there unless it is scrolled by again. This div also contains filters that will hide/show content below based on what is selected. Because of this, I believe I have to run ScrollTrigger.refresh() to update the elements (I am lazyloading images using ScrollTrigger.batch()). When refresh runs, my pinned div falls behind the navbar and doesn't reappear until a scroll takes place. It also causes issues with the future scrolling and will no longer pin to the top at certain points.

 

I have a codepen created with a button at the bottom of the last section that calls ScrollTrigger.refresh() to replicate the issue. I think it might be an issue with my toggleActions values, but I haven't been able to find a combination that works properly.

 

Thank you so much for your help!

See the Pen PoZZVqw by nvatland (@nvatland) on CodePen

Share this post


Link to post
Share on other sites

Aha, your test case revealed an issue in ScrollTrigger - you were using toggleClass and when refreshing, it wasn't removing the class before calculating the positions. Your class was affecting positioning, hence the problem. Each time you clicked "refresh" it was basically toggling the class on that element back and forth. 

 

Thanks for the reduced test case! It made it much quicker to identify the issue.

 

I made that change for the next release which you can preview at https://assets.codepen.io/16327/ScrollTrigger.min.js (you may need to clear your cache) - does that work better for you? 

 

By the way, toggleActions are totally pointless if you don't have an animation linked to the ScrollTrigger. And it's absolutely fine to set up a ScrollTrigger without an animation. It's quite useful in fact. I'm just saying it's a waste to define toggleActions because those just tell ScrollTrigger what to do to the associated animation. :)

 

  • Like 4
  • Thanks 1

Share this post


Link to post
Share on other sites

Yes, that worked! Thank you so much 😊

 

And ah okay perfect, noted on the toggleActions!

  • Like 1

Share this post


Link to post
Share on other sites

Hey @GreenSock one more question related to this.

 

I have images lazy loading using .batch() and then being filtered out by that pinned button. However, sometimes when a filter occurs there are some images that don't load but are in view.

 

I have updated my codepen to include this– I moved the refresh scrolltrigger button up to the top and then the images are in the third section with their source swapping at 125%. When you click the button it is randomly hiding some of the content. If you press it a few times you will most likely run into some images not loading even though they are past the 125% mark.

lazyloadrefresh.jpg

Share this post


Link to post
Share on other sites

I can't seem to replicate it in the latest beta - can you? (You might need to clear your cache). 

 

I did notice, though, that you may have things set up incorrectly if your goal is to have the images only lazy-load once. Did you want them to re-load every time they enter from the bottom? If not, maybe set once: true? 

 

Also you have the "end" set up to be when the bottom of the element hits the bottom of the screen, but I think it'd be much better to set it to "bottom top" so that the onEnter fires from ANYTHING on the screen. Currently, if you refresh while scrolled down to an area that's filled with images, most of them won't fire their onEnter because they're not within their active area. ScrollTrigger is doing what you ask, but I just don't think it's the most intuitive behavior for the web page, that's all. 

  • Like 2

Share this post


Link to post
Share on other sites

@Jack

 

Quick question, wondering if I'm experiencing the same or a similar issue (my intention isn't to hijack this thread). If not, I'll create my own thread :)

 

I'm building an animation with scrollTrigger and scrub, mostly animating xPercentage or yPercentage values.

When I resize my browser window the values for the start and end trigger positions don't seem to update/reflect the changed window dimensions. Is this the same issue?

 

BTW, this plugin is the bees knees, truly jaw dropping. I've decided to renew my membership to support you guys. About that: is the permanent license basically a lifetime license?

Share this post


Link to post
Share on other sites

@ynamite got a minimal demo that we can take a look at? 

 

And yes, the permanent license gives you a lifetime commercial license. However, updates to files stop after 3 years (though you can purchase individual updates for a reduced price after that).

Share this post


Link to post
Share on other sites
9 hours ago, ynamite said:

I'm building an animation with scrollTrigger and scrub, mostly animating xPercentage or yPercentage values.

When I resize my browser window the values for the start and end trigger positions don't seem to update/reflect the changed window dimensions. Is this the same issue?

 

Like @ZachSaucier said, a CodePen would be SUPER helpful. It's just very difficult to troubleshoot blind. We'd love to help. Please make sure you're using the latest version of ScrollTrigger too. 

 

9 hours ago, ynamite said:

BTW, this plugin is the bees knees, truly jaw dropping. I've decided to renew my membership to support you guys.

That's so cool! Thanks for your generous support, @ynamite. We really couldn't do what we do without folks like you. 🙌

Share this post


Link to post
Share on other sites
14 hours ago, ZachSaucier said:

@ynamite got a minimal demo that we can take a look at?

 

@ZachSaucier I've managed to fix the problem while whipping up a demo, but thanks for your fast reply (mind boggling how quickly you guys reply, every time).

Turns out I had two issues: I was dynamically loading CSS after initializing the scrollTrigger in question.

Secondly I hadn't realized that when initializing scrollTrigger on an element, it wouldn't automatically set the triggers (startTrigger and endTrigger) as that element. Setting the triggers explicitly seems to have helped.

 

4 hours ago, GreenSock said:

Like @ZachSaucier said, a CodePen would be SUPER helpful. It's just very difficult to troubleshoot blind. We'd love to help. Please make sure you're using the latest version of ScrollTrigger too. 

 

That's so cool! Thanks for your generous support, @ynamite. We really couldn't do what we do without folks like you. 🙌

 

@GreenSock

Sure thing, I'll supply a demo next time :) don't mention it, it's the least I can do and only fair.

 

One last question: how many individual scrollTriggers is it safe to have on a single page, performance-wise? In this case, in order to animate in/out different content types with different animations, I'm using maybe 5 or 6 scrollTriggers per page.

Share this post


Link to post
Share on other sites
12 hours ago, ynamite said:

One last question: how many individual scrollTriggers is it safe to have on a single page, performance-wise? In this case, in order to animate in/out different content types with different animations, I'm using maybe 5 or 6 scrollTriggers per page.

I'd probably try to keep it under 1,000 :)

 

Seriously, ScrollTrigger is hyper-optimized for speed. It does all the difficult work of calculating intersection points up front (on refresh()) and then all it's doing the rest of the time is checking the scroll position. It doesn't do expensive operations like getBoundingClientRect() on every scroll event or anything like that. The feedback we've gotten from the community is that ScrollTrigger is surprisingly fast, so I wouldn't fret about using 10 triggers on a page. 

  • Like 2

Share this post


Link to post
Share on other sites
On 6/12/2020 at 8:20 PM, GreenSock said:

I can't seem to replicate it in the latest beta - can you? (You might need to clear your cache). 

 

I did notice, though, that you may have things set up incorrectly if your goal is to have the images only lazy-load once. Did you want them to re-load every time they enter from the bottom? If not, maybe set once: true? 

 

Also you have the "end" set up to be when the bottom of the element hits the bottom of the screen, but I think it'd be much better to set it to "bottom top" so that the onEnter fires from ANYTHING on the screen. Currently, if you refresh while scrolled down to an area that's filled with images, most of them won't fire their onEnter because they're not within their active area. ScrollTrigger is doing what you ask, but I just don't think it's the most intuitive behavior for the web page, that's all. 

 

Thanks for the tip on the once: true, I updated that. I had end set to "bottom top" in the beginning but switched it to "bottom bottom" because I was still having this issue so I was seeing if that solved it. 

 

I updated my codepen demo with once and end: "bottom top" and also increased the number of images that are loading which is replicating the issue that I am having on my production site. If you click the button before scrolling to the bottom of the page, some of the images aren't loading in until it is refreshed again (try clicking it before as soon as you see the button). I did a console.log of the .batch on my production site and it is still loading the images in the order that they would have originally displayed so if I scroll far enough down and then back up the images will then display.

Share this post


Link to post
Share on other sites

I was able to replicate it using each instead of batch as well. It looks like positions aren't being recalculated when display: none is applied. If you turn markers on you can see that they go down throughout the page (not sure if they should move with the object or not on refresh).

 

Here's the each codepen:

See the Pen eYJBOGB by nvatland (@nvatland) on CodePen

Share this post


Link to post
Share on other sites

I'm a bit lost here...

  1. It looks like you're not just doing a refresh() - you're applying filter-hide class to various elements which explains why they're disappearing. I originally thought you were saying that ScrollTrigger was causing that, but I probably misunderstood. It looks like it's your own script doing that. 
  2. Yes, ScrollTrigger can't map coordinates of elements that have display: none - they're essentially removed from the flow of the document. Perhaps you could use visibility: hidden? 
  3. If you think there's a bug in ScrollTrigger, would you mind creating a reduced test case? The CodePens you're providing have a lot of other stuff going on, so it's hard to sift through all that to find what you're saying you believe the bug is. Perhaps I'm missing something obvious, but a reduced test case would go a long way in helping to clarify things. I definitely want to fix any bugs that may exist in ScrollTrigger, but I'm not seeing any right now. Please make sure you're using the latest beta: https://assets.codepen.io/16327/ScrollTrigger.min.js (you may need to clear your cache)
  • Like 1

Share this post


Link to post
Share on other sites
10 minutes ago, GreenSock said:

I'm a bit lost here...

  1. It looks like you're not just doing a refresh() - you're applying filter-hide class to various elements which explains why they're disappearing. I originally thought you were saying that ScrollTrigger was causing that, but I probably misunderstood. It looks like it's your own script doing that. 
  2. Yes, ScrollTrigger can't map coordinates of elements that have display: none - they're essentially removed from the flow of the document. Perhaps you could use visibility: hidden? 
  3. If you think there's a bug in ScrollTrigger, would you mind creating a reduced test case? The CodePens you're providing have a lot of other stuff going on, so it's hard to sift through all that to find what you're saying you believe the bug is. Perhaps I'm missing something obvious, but a reduced test case would go a long way in helping to clarify things. I definitely want to fix any bugs that may exist in ScrollTrigger, but I'm not seeing any right now. Please make sure you're using the latest beta: https://assets.codepen.io/16327/ScrollTrigger.min.js (you may need to clear your cache)

 

Hi Jack,

 

Sorry I think I wasn't explaining things properly.

 

I am purposely hiding elements with the filter-hide class (display: none) when the button is pressed and then running ScrollTrigger.refresh() as there have been DOM changes. However, on pressing the button it seems that not all elements are being refreshed properly or are being overlooked. If you press the button before scrolling all the way down (and thus loading every image), some that should be visible fail to load until you press the button multiple times.

 

For example, in the attached image, all of the images here should be the same but there are a few that are blank. If I scroll to the bottom of the page and then back up then some of the images will then load.

 

Let me know if this makes more sense. I can try to create a new reduced case as well.

Screen-Shot-2020-06-17-at-1.14.35-PM.jpg

Share this post


Link to post
Share on other sites

I've read your post 3 times and followed your directions and I'm still lost. It seems like you're under the impression that clicking the "refresh ScrollTrigger" button would cause ALL of the images to load, but I don't know why you think that. Your code is hiding a bunch of them and a ScrollTrigger.refresh() wouldn't make them all load anyway. And I cannot replicate what you said about scrolling down and then back up and that causing some of them to load (on the way back up?) 

 

I really think a reduced test case would be much, much easier for us to communicate around. Sorry, I may be missing something obvious. 

  • Like 1

Share this post


Link to post
Share on other sites
59 minutes ago, GreenSock said:

I've read your post 3 times and followed your directions and I'm still lost. It seems like you're under the impression that clicking the "refresh ScrollTrigger" button would cause ALL of the images to load, but I don't know why you think that. Your code is hiding a bunch of them and a ScrollTrigger.refresh() wouldn't make them all load anyway. And I cannot replicate what you said about scrolling down and then back up and that causing some of them to load (on the way back up?) 

 

I really think a reduced test case would be much, much easier for us to communicate around. Sorry, I may be missing something obvious. 

 

Sorry, that's still not what I'm going for. 

 

See the Pen wvMojjm by nvatland (@nvatland) on CodePen

 

This is best viewed in the full view as the screen is too small in the editor view.

 

I created a new CodePen that has buttons that filter the content based on color. So when I click "Show Blue" all of the blue images should be shown and everything else is hidden. I am adding display: none to the ones that are hidden and am not expecting them to lazyload in, but the blue ones that are visible on the screen should all load. However, there are a few scattered throughout that don't load.

 

If I cycle through the different buttons and then go back to blue all of the images will load. If I have scrolled to the bottom (thus loading all of the images) and then click a filter, all of images will be there.

 

In the attached image, I have pressed "Show Blue" without scrolling down. As you can see, the fourth image and the ninth image did not load even though they have entered the stage.

 

I hope this makes more sense!

showblue.jpg

  • Like 1

Share this post


Link to post
Share on other sites

I think it's related to the end position. If I change it to 9999 it works for me.

 

There does seem to be some weirdness going on @GreenSock.

  • Like 1

Share this post


Link to post
Share on other sites

Thanks for the [more] reduced test case, @nvatland. Very helpful. 

 

There are two issues that I see: 

  1. Due to the fact that once: true was defined, things were getting kill()-ed on initial load while the refresh() loop was occurring internally which was throwing off the index (because when you kill() a ScrollTrigger it obviously gets removed from the internal Array...which was in the process of being iterated through). I've resolved that in the next release which you can preview at https://assets.codepen.io/16327/ScrollTrigger.min.js
  2. There was a logic issue which is a little tricky. It has to do with whether or not onEnter/onLeave callbacks get triggered on initial load (or any other refresh) when the scroll position is already PAST the ScrollTrigger (progress: 1). So imagine you've got 100 boxes, but only 10 show up on the screen at any time and you scroll down to boxes 40-50 and then you reload the web page. Should the onEnter fire for boxes 1-39? Technically they didn't just enter the screen, so they shouldn't fire (that's the current behavior). However, what if someone scrolls SUPER fast (after load) so that in a single update, a ScrollTrigger goes from off-the-screen BELOW to off-the-screen ABOVE? You just went past both the onEnter and the onLeave. Should they both fire? I think so. Most people would probably expect that. But on initial load, it's very similar to that (the scrollbar jumps past boxes 1-39 instantly) but most people probably wouldn't expect the onEnter/onLeave to fire for boxes 1-39. See the issue? 

    Likewise, for a ScrollTrigger.batch() call, you probably wouldn't want to get boxes 1-50 in that first onEnter. If you're doing a staggered fade-in animation, for example, users would be sitting there waiting and waiting while 1-39 start fading in before they see the ones on-screen (40-50) start fading in. No bueno. But in a case like yours, perhaps you WOULD want that initial load to contain all the elements "above the fold". 

    Fix #1 above should fix your demo in most cases, but if you scroll far down on the page (past the first blue boxes, for example) and reload the page, then filter the blue boxes (to only show those), then scroll up, you'll see that some aren't loaded. That's not a bug - it's a logic issue. The onEnter never fired for those because they're off-screen (and have always been off-screen at that point). And you're only loading things onEnter which is for when things come in FROM THE BOTTOM, but in this scenario they're technically entering from the TOP (which is onEnterBack). 

    So of course you could adjust your logic accordingly to get triggered in that scenario too, or I'm experimenting with adding a new static ScrollTrigger.limitCallbacks() method that'll let you control the behavior on a global basis. So before you set up any of your ScrollTriggers, you could set ScrollTrigger.limitCallbacks(false) so that ANY ScrollTriggers "above the fold" will have their onEnter called even on the initial load. 

Does that make sense? 

 

I'm open to suggestions on functionality/API. The name that made the most sense to me is limitCallbacks() but if anyone has a better suggestion, I'm all ears. 

 

Let me know if the new ScrollTrigger beta resolves the issues you were running into. 

 

  • Like 2

Share this post


Link to post
Share on other sites

Update: renamed ScrollTrigger.limitCallbacks() from the beta to ScrollTrigger.config() for 3.3.4 to open up future possibilities for configuration, streamlining the API a bit. So:

 

// tells ScrollTrigger to only fire callbacks like onEnter when the active state CHANGES.
// So if you go all the way past a ScrollTrigger (progress: 0 goes all the way to progress: 1
// in one fell swoop), it won't fire. By default, limitCallbacks is false, so onEnter WILL 
// fire in that scenario. 
ScrollTrigger.config({ limitCallbacks: true }); 

@nvatland I'm curious if you had a chance to try the updated beta. Seems to resolve the issue well. 

 

config() docs: https://greensock.com/docs/v3/Plugins/ScrollTrigger/static.config()

  • Like 2
  • Thanks 1

Share this post


Link to post
Share on other sites
On 6/20/2020 at 3:10 PM, GreenSock said:

Update: renamed ScrollTrigger.limitCallbacks() from the beta to ScrollTrigger.config() for 3.3.4 to open up future possibilities for configuration, streamlining the API a bit. So:

 


// tells ScrollTrigger to only fire callbacks like onEnter when the active state CHANGES.
// So if you go all the way past a ScrollTrigger (progress: 0 goes all the way to progress: 1
// in one fell swoop), it won't fire. By default, limitCallbacks is false, so onEnter WILL 
// fire in that scenario. 
ScrollTrigger.config({ limitCallbacks: true }); 

@nvatland I'm curious if you had a chance to try the updated beta. Seems to resolve the issue well. 

 

config() docs: https://greensock.com/docs/v3/Plugins/ScrollTrigger/static.config()

 

It seems to be working great now, thank you so much for your help on this! 

  • Thanks 1

Share this post


Link to post
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.

×