Superloop Posted April 5, 2022 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.
walpolea Posted April 5, 2022 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
Cassie Posted April 5, 2022 Posted April 5, 2022 You can also call ScrollTrigger.refresh() https://greensock.com/docs/v3/Plugins/ScrollTrigger/refresh()
walpolea Posted April 6, 2022 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.
Superloop Posted April 6, 2022 Author 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
GreenSock Posted April 6, 2022 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.
Superloop Posted April 6, 2022 Author 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(); });
walpolea Posted April 6, 2022 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.
GreenSock Posted April 7, 2022 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
Stoggy Posted June 1, 2022 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
KeviinCosmos Posted September 21, 2023 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
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