Jump to content


  • Posts

  • Joined

  • Last visited

Recent Profile Visitors

677 profile views

ashthornton's Achievements

  • Week One Done
  • One Month Later
  • One Year In

Recent Badges



  1. I meant that using window.scrollY/pageYOffset to set positions of objects in WebGL causes a lag between DOM and WebGL position. I've just replaced ASScroll with your smooth scroll implementation on my basic DOM/WebGL sync demo and it does seem to work perfectly fine without any lag. And having looked through the ScrollTrigger source code, it does seem to end up just using window.pageYOffset. This is interesting! Codepen here: https://codepen.io/ashthornton/pen/874833fdebc032bedd0cf61e9eac3ee9 The idea behind performant smooth scroll has always been to create a 'virtual scroll' using the wheel delta to set the scroll position, since reading window.pageYOffset causes the browser to layout so its an expensive property to access in a requestAnimationFrame loop and then translate an element based on that. Looks like I have some investigating to do
  2. Hey, I'm the author of ASScroll so just thought I'd chime in here Just for clarification - the iframe issue is that once your mouse enters an iframe, the `wheel` event on the parent window stops firing since it's not linked to any sort of overscroll behaviour. It won't fire until your mouse leaves the iframe again, which is problematic especially on trackpads since the mouse will sort of stay in the same position as you try and continue to scroll past with two fingers. The reason ASScroll works in those edge cases like when hovering over an iframe or using the middle mouse button to scroll, is the same reason the GSAP smooth scroll implementation also works (as far as I can see). The GSAP version looks like it listens to the `scroll` window event and updates the transform accordingly. I would say that it exclusively listens to this event since I can see the native scrollbar matching the smoothed scroll position exactly, but I can also see some `wheel` events so it may be using a combination, like ASScroll. Using the native scroll position like this means that you're just extending the scroll functionality rather than overriding it, which is what the other smooth scroll libraries do, like Locomotive and smooth-scrollbar. They exclusively listen to the `wheel` event, so they need to essentially rebuild the entire native scroll functionality again. This means they use arbitrary values for when they manually recreate keyboard scrolling (arrow keys, pg up/down, home/end etc.) which won't match the scroll speed the user has defined in their OS - this also introduces a whole host of issues like now having to deal with keypresses when in an input field, for example. And they will never be able to deal with the iframe issue unless they also listen to the `scroll` event. So I think the difference between the GSAP smooth scroll implementation and ASScroll, is that ASScroll uses a hybrid setup - `wheel` if its available to provide the high-performance 'virtual scroll' setup, and `scroll` if `wheel` isn't available for whatever reason - like keyboard navigation, hovering an iframe, using a screen reader etc. I'd be curious to see how the GSAP version handles syncing DOM with WebGL for example, which nowadays is the primary requirement for having to use 'virtual scroll' since listening to `window.scrollY/pageYOffset` causes lag between the two.
  3. Thanks for taking the time to explain that @GreenSock, it definitely makes sense and I've now got a nice setup that allows me to create page entrance animations utilising ScrollTrigger. Really appreciate the whole library and you catering for us scroll-jackers And on that, thanks for featuring my library in the docs! I know you made ScrollTrigger to avoid scroll-jacking, I similarly made ASScroll to fix the issues in every smooth scroll lib I've seen, they all seem to unnecessarily take over native functionality even down to manually mapping keyboard buttons to scroll, so I appreciate every bit of exposure for it
  4. Ok I've updated that Codepen with a reduced example to make sure we're seeing the same thing. So in its current state, the h1s all turn red immediately. Do you also get the same result? All the h1s turn red immediately when using the singular .to tween. Even though the ScrollTrigger instance is disabled immediately after creation and enabled 2 seconds later in the .delayedCall. This is the unexpected behaviour as it's not waiting 2 seconds to enable. But if you disable the singular .to tween and enable the .timeline the h1s turn red after the set 2 seconds. This is the expected behaviour. Interestingly, with the singular tween enabled all h1s that are visible in the viewport immediately turn red, but if you scroll down before the 2 seconds you'll see they are still black and then turn red after the 2 second delay.
  5. I just remembered what I was doing @GreenSock. See the CodePen. The method works when the ScrollTrigger instance is attached to a Timeline, but not when its a singular Tween: Update: using your example, it seems that changing the start property allows it to be delayed, but when it's the default that's when it starts immediately. https://codepen.io/ashthornton/pen/48de17aa88051235647253ef4e6ed76c
  6. My comment really was in response to the solution that ZachSaucier posted as I found it contradictory that you'd need to create a timeline that pauses itself as soon as it starts playing. It seemed that was the only way which was strange, hence the feedback, but having looked at your demo code I realised I must've been targeting the wrong thing/tween reference or something, I can't remember now! Disabling the scrollTrigger instance immediately after creation and enabling again later works. Thanks for clarifying!
  7. Thanks for the tip @ZachSaucier. It's a shame ScrollTrigger doesn't pay attention to the paused option in a tween/timeline by default and wait til you hit play() or something similar to activate, rather than using this workaround. But it works so thank you!
  8. I've had a look around to see if anyone else has asked about this but couldn't find anything in the sea of ScrollTrigger questions recently! Basically I want to know if there's a way to set up tweens for a page which have ScrollTrigger attached, but have the ScrollTrigger disabled/inactive until I say so. For example, when you're loading a page you'd build all your tweens, but you'd have a page loader/transition covering the page. Meaning the trigger elements are technically in view but you don't want them to trigger the tween until you've finished the loader/transition and hit go. I can't find anything in the docs apart from the enable/disable functions on a ScrollTrigger instance, but this doesn't seem to work, even if the tweens are paused before I run .enable().
  9. Yep! I even looked at https://greensock.com/docs/v3/Plugins/ScrollTrigger/static.defaults() and it didn't register. It's getting late... Thanks again
  10. I've noticed that you'd of course have to specify a custom scroller property for every scrollTrigger you create and for typical virtual scroll setups that would be the same element each time. Is there a way to override that globally? If not I think that'd be super helpful in this scenario. It can then be overridden at the lower level when needed, and you'd update the global element again if navigating via PJAX for example.
  11. Amazing thank you. Looking forward to diving in!
  12. @GreenSock Do you have any idea if, and when you might release a version with this `scrollerProxy` function included?
  13. Quickly plugged my smooth scroll library into this to test and it seems to be working nicely. I'll definitely be testing further! https://codepen.io/ashthornton/pen/314576d606f39fb246bf5dcad6fb978d
  14. Setting it to 240 removes the throttle on my 144hz display but of course people with 240hz+ might see stuttering. To be honest, beyond 240 it just gets a bit ridiculous and I'm not even sure if the stutter would be visible when throttling from say 360hz (which was recently announced) down to 240. I think 240 is a good compromise All of this pushing crazy refresh rate numbers has me thinking
  15. 60fps definitely isn't janky and even on a 60hz+ refresh rate screen it looks smooth, i.e. when watching 60fps videos/gaming but it seems that GSAP's attempt to throttle to a maximum of 60 even though the browser might be able to go higher definitely causes a stutter that you wouldn't normally see. Not exactly, as far as I can see: Here in v2 https://github.com/greensock/GSAP/blob/2.1.3/src/uncompressed/TweenMax.js#L6479 If _fps hasn't been set, which it isn't by default, it allows the next tick to be dispatched as soon as browser RAF is fired - bypassing any check of a negative overlap that might be caused by _gap Here in v3 https://github.com/greensock/GSAP/blob/master/src/gsap-core.js#L857 That _fps check is removed so it relies solely on whether there is a negative overlap or not. Which does happen when RAF has fired more than once in 1/60 seconds. On a 60+hz display if you log out overlap you'll see negative values which will cause the conditional to be skipped and the internal event to not be dispatched. So setting _fps to -1 forces a positive overlap every time and we get an un-throttled loop. Hopefully that all makes sense and I've read the code right. If it does then you can see why setting fps to 120 or 144 would also remove the throttle but the reason I won't do that is because there are already higher refresh rate screens out there and I don't want to limit those. I can set up a reduced demo if you'd like but it'd just be a square translating across the screen or something then enabling and disabling gsap.ticker.fps(-1) on v3, then the same on v2 without any special config. Of course you need a screen with a refresh rate higher than 60hz to see any of this!