ashthornton
Content Type
Profiles
Forums
Store
Blog
Product
Showcase
FAQ
Downloads
Posts posted by ashthornton
-
-
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.
- 4
- 1
-
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
- 1
-
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.
- 1
-
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.See the Pen 48de17aa88051235647253ef4e6ed76c by ashthornton (@ashthornton) on CodePen
- 1
-
31 minutes ago, GreenSock said:
Can you elaborate? I have a feeling I may be misunderstanding, but one of the main purposes of applying a ScrollTrigger to an animation is so that the ScrollTrigger would control the animation (play, pause, scrub, whatever). It automatically pauses it initially. So why would it matter if you also paused it first? Like...how exactly are you wanting it to behave in an ideal world? If ScrollTrigger sees that you pause the tween on the outside, you want it to refuse to play/restart/scrub/whatever? It'd need to "watch" the tween to sense when you call play() and then...take control in which case it may or may not actually play depending on the scroll position? If so, that seems pretty odd to me (to call play() on an animation and it refuses to play).
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!
- 2
-
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!
-
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().
-
6 minutes ago, GreenSock said:
Sure...
ScrollTrigger.defaults({ // you can set any defaults here. scroller: ".container" });
Does that help?
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
-
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. -
5 minutes ago, GreenSock said:
Should be within a few days. Definitely this week. 👍
Amazing thank you. Looking forward to diving in!
-
@GreenSock Do you have any idea if, and when you might release a version with this `scrollerProxy` function included?
-
Quickly plugged my smooth scroll library into this to test and it seems to be working nicely. I'll definitely be testing further!
See the Pen 314576d606f39fb246bf5dcad6fb978d by ashthornton (@ashthornton) on CodePen
- 1
-
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
- 1
- 1
-
1 hour ago, GreenSock said:
-
GSAP is built on top of
requestAnimationFrame
by default and most browsers max out at dispatching those events 60 times per second. It's not a limitation that GSAP imposes. Most people can't even perceive more than 60fps. I'd hardly call 60fps "janky"
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.
1 hour ago, GreenSock said:- GSAP v2 used exactly the same logic - I'm not sure why you think v2 was somehow better.
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 negativeoverlap
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!
-
GSAP is built on top of
-
On 1/21/2020 at 10:57 PM, GreenSock said:
GSAP is time resolution-independent, meaning it calculates the values based on the exact time of the update. It does NOT assume that you'll run at 60fps and pre-calculate values or anything like that. With some animation engines, if your framerate slows down to 30fps, for example, when it was assuming you'd run at 60fps, all your animations end up taking twice as long (bad). Not GSAP. Even if your frame rate drops substantially (or increases), it'll always render the values where they're supposed to be based on the overall time, not FPS. It also has some advanced features like lag smoothing that are automatically enabled to heal from CPU spikes. And the timing mechanisms are identical in v2 and v3.
Does that answer your questions?
I'm really struggling to understand why you noticed a difference in v2 vs v3 but nobody else can and the only significant difference (which really shouldn't be significant at all in terms of performance) is that v2 calculates the matrix()/matrix3d() instead of using values like translate()/translate3d() + rotate(), etc. I'd actually think v3 would be a bit faster in that regard.
I've experienced this issue after migrating to v3 from v2 also. After some digging I found the difference was that GSAP is now defaulting to 60 fps if a manual override isn't provided: https://github.com/greensock/GSAP/blob/master/src/gsap-core.js#L843
So on a screen with a refresh rate above 60hz GSAP tries to throttle the rAF loop resulting in janky animation.
My workaround has been to set the fps to -1 like so:
gsap.ticker.fps(-1)
Would it be possible for GSAP to allow an option to not limit the fps? Since >60hz screens are becoming more and more popular, particularly in mobiles, I think this is important.
ScrollTrigger Snap + Smooth Scroll causes odd behavior
in GSAP
Posted
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:See the Pen 874833fdebc032bedd0cf61e9eac3ee9 by ashthornton (@ashthornton) on CodePen
The idea behind performant smooth scroll has always been to create a 'virtual scroll' using the
wheel
delta to set the scroll position, since readingwindow.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