darkroomengineering / lenis

How smooth scroll should be
https://lenis.darkroom.engineering
MIT License
7.33k stars 316 forks source link

Lenis scroll with GSAP Observer plugin - Mouse wheel Firefox #311

Closed jackkemmish closed 3 months ago

jackkemmish commented 3 months ago

Hi there, hope you're good!

Describe the bug I am using Lenis for smooth scrolling, and also using GSAP's Observer plugin to handle some scrolling events for zooming.

I have noticed though, on Firefox, using an apple mouse scrolls perfectly fine over the Observer target, but using a proper mouse wheel such as on a Logitech mouse, it seems to be throttling/lagging. This is however fine on Chrome and Safari though - it seems to just be a Firefox issue.

To Reproduce I have this codepen with a simplified set up. Lenis is in there, along with the GSAP Observer plugin.

If you open in Firefox and use an apple mouse for example, it scrolls fine when scrolling over the target container, but then switch to a mouse with a proper wheel, it feels like there's some throttling happening.

Then open in Chrome/Safari and do the same and you will see it feels fine.

https://codepen.io/jackkemm/pen/jORbdKa

Thanks in advance :)

Jack

clementroche commented 3 months ago

I don't see any scrolling animation on your example

jackkemmish commented 3 months ago

Hi, sorry I might not have been clear enough, the actual animation working is redundant here, the issue is just scrolling over the container that has the animation using a mouse with a physical wheel in firefox, there seems to be a lag.

clementroche commented 3 months ago

Interesting, it will be hard to figure it out since it might come from GSAP Observer itself

jackkemmish commented 3 months ago

Yeah sorry I was unsure as to where would be best to ask the question, and initially I thought here. Seems to be one of those weird things between browsers 🤦‍♂️ However, commenting Lenis out does fix the scrolling throttling, so I wonder if there could be conflicting events between Lenis and GSAP here maybe?

I'm going to reach out to GSAP and see if they can shed some light on this potentially too - they might have some sort of scroll event on the target element which might be causing a conflict maybe 🤷‍♂️

clementroche commented 3 months ago

Lenis internally uses WheelEvent.deltaY so most probable that GSAP Observer changes this value that is then propagated. I will investigate on my side anyway and reach GSAP Team.

jackkemmish commented 3 months ago

@clementroche okay thank you! I'll hold off reaching out then. Thanks again!

clementroche commented 3 months ago

https://codepen.io/ClementRoche/pen/jORWZEr here is a minimal demo showing that GSAP Observer is modifying the deltaY in some ways (see console)

Also, adding capture:true fixes the issue 😅

window.addEventListener( "wheel", (e) => { console.log("window capture", e.deltaY); }, { capture: true } );

jackkemmish commented 3 months ago

Oh yeah I can see there's a bit of difference intermitently on scroll 🤦‍♂️

Nice find using capture: true! I presume it's to do with propogation of events in that case. Is the use of capture something to be added into Lenis or GSAP's plugin would you think?

clementroche commented 3 months ago

capture:true shouldn't be added as default in my opinion. That would be a hack

jackkemmish commented 3 months ago

Yeah I guess it would cause other issues down the line :/

clementroche commented 3 months ago

@jackkemmish GSAP team is aware and will investigate

jackkemmish commented 3 months ago

Amazing! You've been a great help 💪

jackdoyle commented 3 months ago

This is actually a super weird Firefox behavior that is NOT due to GSAP/Observer altering anything at all.

Summary:

If event.deltaMode is checked BEFORE event.deltaY/X, Firefox honors the original deltaMode and reports the deltaY/X accordingly, but if it is NOT checked in that order, deltaY/X is reported in pixels!

GSAP's Observer checks the deltaMode in order to properly convert its deltaY into pixels if necessary. So in this case, for example, with a regular mouse (not Apple Magic Mouse), Firefox reports a deltaMode of 1. Since Observer checks that, the event reports deltaY accordingly, in lines (not pixels). In your demo, you don't check deltaMode at all, thus it reports in pixels. That's why the deltaY was smaller - it was reporting the delta in lines, not pixels, which one could argue is correct. I personally think it is incredibly strange to alter deltaY simply based on whether or not deltaMode was checked previously.

Notice that if you completely remove Observer from the equation, and simply check event.deltaMode FIRST, you'll get the same result: https://codepen.io/GreenSock/pen/QWPyZKE?editors=0010

So you might just want to update Lenis so that it properly checks deltaMode and adjusts the value accordingly. For example, you could use a multiplier:

let multiplier = (e.deltaMode === 1 ? lineHeight : e.deltaMode === 2 ? window.innerHeight : 1), // make sure you set a lineHeight variable somewhere before this.
    deltaY = e.deltaY * multiplier;

Sources: https://groups.google.com/g/mozilla.dev.platform/c/fUXLgaSoeLI/m/ubt__u7MAQAJ?pli=1

https://github.com/mdn/content/issues/11811

Does that clear things up?

clementroche commented 3 months ago

Woaw, thank you @jackdoyle for your expertise, it's a very weird behavior from Firefox indeed. Imma take care of implementing that in Lenis.

jackkemmish commented 3 months ago

Hi @jackdoyle and @clementroche,

Thank you both for the help on this! Look forward to pulling down the latest version 💪

clementroche commented 3 months ago

it should be fixed in v1.0.41

jackkemmish commented 3 months ago

@clementroche amazing thank you! Will take a look 👍