Superloop Posted April 5, 2022 Share Posted April 5, 2022 Hi! I'm trying to use Scrollsmoother but I have a problem with lazyload images. The scroll doesn't refresh or update when images are loaded. Maybe it could nice a method for refresh or update scrollsmoother. Anyone has a solution for this? Thanks! See the Pen OJzQgRQ by marctaule (@marctaule) on CodePen Link to comment Share on other sites More sharing options...
walpolea Posted April 5, 2022 Share Posted April 5, 2022 I ran into the same issue with a tabbed component changing the content height. The only solution I found was to dispatch a resize event which ScrollTrigger refreshes values on pretty gracefully. window.dispatchEvent(new Event("resize")); This also works as images lazily load in, but there is some undesired jank as things recalculate while the scrolling is mid-tween document.querySelectorAll("img[loading=lazy]").forEach((i) => { i.addEventListener("load", (e) => { window.dispatchEvent(new Event("resize")); }); }); 1 Link to comment Share on other sites More sharing options...
Cassie Posted April 5, 2022 Share Posted April 5, 2022 You can also call ScrollTrigger.refresh() https://greensock.com/docs/v3/Plugins/ScrollTrigger/refresh() Link to comment Share on other sites More sharing options...
walpolea Posted April 6, 2022 Share Posted April 6, 2022 Thanks! This works. I wrote this off because I had tried: const sm = SccrollSmoother.create(...) //... then later sm.scrollTrigger.refresh() Which did not work. Link to comment Share on other sites More sharing options...
Superloop Posted April 6, 2022 Author Share Posted April 6, 2022 6 hours ago, walpolea said: Thanks! This works. I wrote this off because I had tried: const sm = SccrollSmoother.create(...) //... then later sm.scrollTrigger.refresh() Which did not work. Oh nice!! This works for me Link to comment Share on other sites More sharing options...
GreenSock Posted April 6, 2022 Share Posted April 6, 2022 Yeah, I definitely wouldn't call .refresh() after every single image load - I'd set up a simple queue system that only calls ScrollTrigger.refresh() once ALL of the images finish loading. Link to comment Share on other sites More sharing options...
Superloop Posted April 6, 2022 Author Share Posted April 6, 2022 12 hours ago, walpolea said: Thanks! This works. I wrote this off because I had tried: const sm = SccrollSmoother.create(...) //... then later sm.scrollTrigger.refresh() Which did not work. I made some tests but it doesn't work... I edit my codepen. You will see you can get "last" div. See the Pen OJzQgRQ by marctaule (@marctaule) on CodePen If I use refresh in every image loaded, it seems that works but there are some performance problems. document.addEventListener('lazyloaded', function(e){ smoother.ScrollTrigger.refresh(); }); Link to comment Share on other sites More sharing options...
walpolea Posted April 6, 2022 Share Posted April 6, 2022 I think it's less performance problems and more that the refresh stops the existing scroll tween, causing a stuttering effect. Given the nature of lazy-loaded images (which load as you scroll them near the viewport) I'm not sure there is much to be done, perhaps wait until the velocity is closer to 0 like this: let needsToRefresh = false; document.addEventListener('lazyloaded', function(e){ needsToRefresh = true; refresh(); }); function refresh() { if( needsToRefresh && smoother.getVelocity() < 0.01 ) { ScrollTrigger.refresh(); needsToRefresh = false; } else if( needsToRefresh ) { requestAnimationFrame(refresh); } } Still not the best experience. Definitely the killer feature would be for gsap to somehow not stop the scrolling tween as ScrollTrigger refreshes. Link to comment Share on other sites More sharing options...
GreenSock Posted April 7, 2022 Share Posted April 7, 2022 4 hours ago, Marc Taule said: If I use refresh in every image loaded, it seems that works but there are some performance problems. You had a typo in your code that was throwing an error. I'm not sure why you were trying to call .refresh() on the smoother's ScrollTrigger (before your images even loaded). I didn't realize you were using a different library and only loading the images on-demand. In that case, yes, you'd need to at least call .refresh() on the individual ScrollTrigger associated with that newly-loaded image. Originally, I thought you were just starting the load of all the images after your page loaded (without the images), so this is what I was talking about: function onLoadImages(selector, callback) { let images = gsap.utils.toArray(selector), onLoad = e => { images.splice(images.indexOf(e.target), 1); images.length || callback(); }; images.forEach(img => img.addEventListener("load", onLoad)); } onLoadImages(".lazyload", ScrollTrigger.refresh); But of course that won't work if you're only loading each one when the scroll reaching a certain position. I have made some improvements in the next release which I'm using in this fork: See the Pen KKZovwj?editors=0010 by GreenSock (@GreenSock) on CodePen Does that behave more like what you hoped? 2 Link to comment Share on other sites More sharing options...
Stoggy Posted June 1, 2022 Share Posted June 1, 2022 On 4/7/2022 at 7:07 AM, GreenSock said: You had a typo in your code that was throwing an error. I'm not sure why you were trying to call .refresh() on the smoother's ScrollTrigger (before your images even loaded). I didn't realize you were using a different library and only loading the images on-demand. In that case, yes, you'd need to at least call .refresh() on the individual ScrollTrigger associated with that newly-loaded image. Originally, I thought you were just starting the load of all the images after your page loaded (without the images), so this is what I was talking about: function onLoadImages(selector, callback) { let images = gsap.utils.toArray(selector), onLoad = e => { images.splice(images.indexOf(e.target), 1); images.length || callback(); }; images.forEach(img => img.addEventListener("load", onLoad)); } onLoadImages(".lazyload", ScrollTrigger.refresh); But of course that won't work if you're only loading each one when the scroll reaching a certain position. I have made some improvements in the next release which I'm using in this fork: Does that behave more like what you hoped? That works like charm for me! 1 Link to comment Share on other sites More sharing options...
KeviinCosmos Posted September 21, 2023 Share Posted September 21, 2023 On 4/5/2022 at 10:57 PM, walpolea said: I ran into the same issue with a tabbed component changing the content height. The only solution I found was to dispatch a resize event which ScrollTrigger refreshes values on pretty gracefully. window.dispatchEvent(new Event("resize")); This also works as images lazily load in, but there is some undesired jank as things recalculate while the scrolling is mid-tween document.querySelectorAll("img[loading=lazy]").forEach((i) => { i.addEventListener("load", (e) => { window.dispatchEvent(new Event("resize")); }); }); THANK YOU SOOOO MUCH!!!!! ❤️ 1 Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now