why is deltaY on `wheel` event different between mac and windows? - javascript

When I try to get the scroll speed of a user I get inconsistent results between mac and windows.
to reproduce
Open this codesandbox
With a mouse, scroll down 1 "tick" (use a mouse that doesn't have smooth scroll)
problem
Using the exact same hardware (mouse / monitor) and browser (chrome):
on Windows I get a value of 125
on Mac I get a value of around 12
I need a way to know how fast the user scrolled that gives comparable results for all operating systems.
more context
This is for a "infinite canvas" type application (like tldraw).
I would like to "zoom out" when the user scrolls backwards and "zoom in" when the user scrolls in.
I want to use the scroll speed (and not just the scroll direction) because otherwise it feels clunky
I know that it's possible because figma can zoom in/out based on mouse wheel speed. Though they use webgl so not sure if they have access to properties that the normal wheel event doesn't have
I can't simply check if deltaY is > 100 because on mac deltaY can get over 100 when the user scrolls fast
I tried every solution from this question. None of them worked across mac/windows

Related

How do you resolve scrollTo stutter on iPhones?

I am using a Muuri grid with draggable items. On desktop, users can use the mousewheel to scroll; however, I had to add an event handler to check if the user holds the item for x time, then they can drag the item. If they immediately move a certain distance, it prevents dragging and programmatically scrolls the view with window.scrollTo.
This works fine on Android and Windows touch screens but the screen jumps around on iPhones. Worse on Safari but still occurs on Chrome. I tried using webkit style atrributes that some articles mention for smoother scrolling, used different scroll behaviors, made sure calculations lead to a top, whole number value (only setting top) of 0 or higher, and the only thing that made a difference was setting a delay. A higher delay (100ms) between scrollTo calls seems to resolve it but isn't smooth to the user.
Content for the move event is simply the method call:
window.scrollTo({top: initialTop + yStart - yEnd})

Pointer Events on mobile creates new pointerId on every pointerdown

To begin, I have read the documentation that says pointerId conveys no meaning
but to some extent it feels like it does.
When retrieving events from pointerdown on a desktop computer you can see that the pointerId property is always 1. I use this to verify if pointerdown event is coming from a mouse click.
However, when I open the Chrome developer tools and use the responsive mode and change it to a mobile device, let's say Pixel 2, and I click on the screen (which is simulated as a touch event) I get an incrementing pointerId on every click.
Now again, I understand it doesn't have a meaning but why does it stay 1 on desktop but go up infinitely on mobile?
I have inserted a simple snippet which when you run on the page it'll show 1 every click and if, you're on a desktop, click on full page and switch to responsive mode and pick a mobile device, it'll show an incrementing value.
window.addEventListener('pointerdown', (event) => {
console.log(event.pointerId);
});
Update
Thanks to the comments I realize that pointerId increments every time because there could be who knows how many fingers touching the screen of a mobile device so there is no way to differentiate them from others.
Why do I need (want) to keep track of pointerId?
Let's say I'm making an application that on desktop only needs the 1 mouse pointer but on mobile it requires 2 fingers to be used to interact with the application.
I need to keep track of where the left finger has been on the screen and what events it has caused and the same for the right finger. The problem comes where the incrementing pointerId comes in is there is no way for me to tell which finger is touching the screen.
Has anyone come across a solution for a problem like this?

Android browser touchend event bug workaround

I've been developing a mobile site for my homepage and I have run into an issue when hooking into mobile touchevents. Basically I would like to accomplish the following:
User scrolls down
on touchend event is fired --> a function is called to figure out the amount of the document that is hidden above after the scroll (like jQuery scrollTop)
program takes action based on the amount of the document that is hidden up top
My issues are the following. So touchend works like expected in iOS, when the user lifts her finger the function makes a call to jQuery.scrollTop() which gives me a pixel value for how much the user has scrolled down. However on Android Browser devices it seems that the jQuery.scrollTop() value is calculated on touchstart. That is to say the event doesn't fire off properly, I get the correct pageX & Y coordinates from the touchend event, however scrolltop() returns the value from when the user started scrolling. I've checked around on the inet and this seems to be a known android browser bug, what I want to know is if there a decent workaround for this issue i.e. one that doesn't involve preventing the default scroll behaviour!? Thanks in advance!
Are you taking into account smooth scrolling? or just basic scrolling?
With basic scrolling you should be able to get the correct value simply by using document.body.scrollTop
Let me know if there is an issue

Controlling Mouse Wheel Scroll Distance?

If you've used a Mac desktop machine, one of the first things you'll notice is that scrolling is different on a Mac than on a Windows desktop.
Windows desktops scrolls in big chunks - multiple lines at a time.
Mac desktops have smooth scrolling - a few pixels at a time.
The difference is pretty obvious when you look at scroll-oriented websites such as http://benthebodyguard.com or http://nikebetterworld.com
Is there a means by which we can control that scroll distance in the browser using javascript?
How the scroll wheel works is dependent on the users configuration of the scroll wheel, and isn't up to you. Users can choose how far the scroll goes.
Even if you were to hack something in place to get this working, I certainly wouldn't recommend it. Not everyone has fast machines that make such smooth scrolling a reasonable task.
You could implement your own scrolling method. Override the default behavior in JS and you'll get the same scrolling in all browsers. $(document).scroll(); should do the trick and do your own calculations and scrolling inside of it.

Does Android browser lock DOM on touchStart?

I'm trying to build a menu with 5 blocks that the user can spin around.
You can see a demo here: http://m.iijax.com/menu.php
Works fine on iPhone, (if a little sluggish sometimes, but that is beside the point :p ) if i draw my finger more then 90 pixels (which i set as a limit) in either direction the menu spins.
On Android (2.1, a Samsung Galaxy S) however the menu does nothing until i release my finger from the screen, I've tried adding an alert on the 2 functions that changes a bunch of classes around to spin the menu either to the right or left and they do get triggered as I draw my finger.
So my best guess is either the browser locks access to the DOM until touchEnd, or it blatantly cheats and simply shows me some kind of screenshot of the page awaiting touchEnd.
Can anyone confirm either of these theories? I've spent about an hour searching here and on google and found nothing, but maybe I haven't found the rightsearch terms.
I've tried lots of swipe and slider examples I've found however and haven't found anything that animates in real time as i draw my finger.
Would also be interesting to know if this menu works on newer Android versions.

Categories

Resources