jquery / jquery-mousewheel

A jQuery plugin that adds cross-browser mouse wheel support.
Other
3.9k stars 1.69k forks source link

Too slow scrolling #66

Closed h4mpy closed 10 years ago

h4mpy commented 11 years ago

it always scrolls pixel by pixel, no matter how tall content is tested on FF 22, Chrome 28 with jquery 1.10.1

needle2k commented 11 years ago

same here FF 22, chrome 27.x , jquery 1.9.1 / 1.10.1 / 1.10.2

lhunath commented 11 years ago

I believe this may be related to the fact that it doesn't take mouse acceleration into account.

eranimo commented 11 years ago

Any update to this? It's pretty breaking...

brandonaaron commented 11 years ago

I'm guessing this is related to the attempt at normalizing the delta values. I'll have to dig into a little more to see if I can narrow it down.

brandonaaron commented 11 years ago

I'm seeing the velocity still taken into account. Can you go to the test page and see if you are getting absolute values > 1? If not are you using a mouse or a track pad or some other device? What operating system? What browser?

screen shot 2013-10-18 at 7 00 39 pm

lhunath commented 11 years ago

I get values between 1-40 for the magic mouse and between 40-120 for a scroll wheel mouse. Note that scroll operations on both mice that would on a normal page result in about the same amount scrolled do not yield comparable values in this test.

On 18 October 2013 20:03, Brandon Aaron notifications@github.com wrote:

I'm seeing the velocity still taken into account. Can you go to the test page http://brandonaaron.github.io/jquery-mousewheel/test/index.htmland see if you are getting absolute values > 1? If not are you using a mouse or a track pad or some other device? What operating system? What browser?

[image: screen shot 2013-10-18 at 7 00 39 pm]https://f.cloud.github.com/assets/13718/1365182/86d16dc6-3851-11e3-8396-08f47f71b8ca.png

— Reply to this email directly or view it on GitHubhttps://github.com/brandonaaron/jquery-mousewheel/issues/66#issuecomment-26638542 .

Maarten Billemont (lhunath) me: http://www.lhunath.com – business: http://www.lyndir.comhttp://masterpasswordapp.com

brandonaaron commented 11 years ago

So just including this plugin (or also binding it?) causes the page to scroll slower than it normally would via the mousewheel? Is it the entire page or just an element that has it bound to?

Side note... It is interesting that you got 40 to 120 for the scroll wheel mouse. It should have been a 1 at the lowest. Did you try the magic mouse first and then the scroll wheel mouse without reloading the page?

I need to dig out my old scroll wheel mouse if I even still have it...

lhunath commented 11 years ago

The page doesn't scroll any different; I was only stating that a scroll operation on the magic mouse or a scroll wheel mouse that would otherwise result in about the same offset scrolled on a page, when performed on one of these test elements, they resulted in log output numbers that did not add up to the same; I didn't do the actual math, I'm just estimating here.

I did indeed use the magic mouse first and then took the scroll wheel mouse; they were both plugged into my mac when I loaded the page. I did not reload the page at any point.

On 19 October 2013 09:45, Brandon Aaron notifications@github.com wrote:

So just including this plugin (or also binding it?) causes the page to scroll slower than it normally would via the mousewheel? Is it the entire page or just an element that has it bound to?

Side note... It is interesting that you got 40 to 120 for the scroll wheel mouse. It should have been a 1 at the lowest. Did you try the magic mouse first and then the scroll wheel mouse without reloading the page?

I need to dig out my old scroll wheel mouse if I even still have it...

— Reply to this email directly or view it on GitHubhttps://github.com/brandonaaron/jquery-mousewheel/issues/66#issuecomment-26649966 .

Maarten Billemont (lhunath) me: http://www.lhunath.com – business: http://www.lyndir.comhttp://masterpasswordapp.com

brandonaaron commented 11 years ago

If you wouldn't mind, try reloading the page before utilizing the other mouse. The numbers should be similar to the magic mouse.

lhunath commented 11 years ago

Verified, when I start with the scroll mouse after a reload, both mice output numbers around 1 - 40+. If I start with the magic mouse, the scroll mouse outputs numbers in increments of 40.

On 19 October 2013 14:49, Brandon Aaron notifications@github.com wrote:

If you wouldn't mind, try reloading the page before utilizing the other mouse. The numbers should be similar to the magic mouse.

— Reply to this email directly or view it on GitHubhttps://github.com/brandonaaron/jquery-mousewheel/issues/66#issuecomment-26656244 .

Maarten Billemont (lhunath) me: http://www.lhunath.com – business: http://www.lyndir.comhttp://masterpasswordapp.com

h4mpy commented 11 years ago

in every test i get value 1 only Mozilla/5.0 (Windows NT 6.1; rv:24.0) Gecko/20100101 Firefox/24.0 with scroll wheel mouse

lhunath commented 11 years ago

even if you scroll really fast?

On 20 October 2013 01:46, h4mpy notifications@github.com wrote:

in every test i get value 1 only Mozilla/5.0 (Windows NT 6.1; rv:24.0) Gecko/20100101 Firefox/24.0 with scroll wheel mouse

— Reply to this email directly or view it on GitHubhttps://github.com/brandonaaron/jquery-mousewheel/issues/66#issuecomment-26665596 .

Maarten Billemont (lhunath) me: http://www.lhunath.com – business: http://www.lyndir.comhttp://masterpasswordapp.com

h4mpy commented 11 years ago

yes, really fast scrolling gives values up to 3

brandonaaron commented 11 years ago

In versions < 3.1 this plugin tried to deal with the various delta values it received. Sometimes it would be a factor of 40, or 3, or 120, or something else entirely. Ultimately, the reported value was inconsistent across the board. In version 3.1 I updated the code so that it would always look for the lowest delta value and use that as the factor so that the delta values would be consistent again across the board. So an absolute value of 1 is valid. Anything greater than that is a multiplier.

There is one major assumption/edge case... it is expected that the user is going to be utilizing a single mouse wheel input (track pad vs mouse for instance) per a session. If the user switches inputs then the lowest delta will be different as illustrated by @lhunath. I believe this is a reasonable assumption in order to finally get a normalized delta value across the board.

brandonaaron commented 11 years ago

So it looks like I need to revisit the delta normalization code. I think I got a little too aggressive in normalizing the delta and lost sight of what information the delta is actually conveying.

brandonaaron commented 11 years ago

Haven't had the chance to properly dig into this but hoping to find some time early next week to get this sorted.

k1w1 commented 11 years ago

I am seeing the same problem of scrolling being too slow. What I am observing is that on Windows (XP, with FF 25 and Chrome 30) the delta values are normalized so that they are always 1 or 2. The pre-normalized values are always 6 & 12 on Firefox (12 when scrolling faster), and always 240 on chrome (regardless of scroll velocity). The normalizing thus reduces the delta to 1 or 2 all the time.

If I remove the normalizing then scrolling is better - Chrome is perfect, but Firefox is still about half the speed of the native scrolling behavior.

On OSX it works fine. If I remove the normalizing on OSX then scrolling becomes too fast (because the lowest scroll value is 3, so the normalizing is dividing the scroll speed by 3).

It seems that the normalization algorithm needs to be a bit smarter - but it is not clear to me if a general algorithm exists. I am puzzled why the browsers differ so much in this parameter.

On further testing I noticed something else interesting on Windows in FF and Chrome. In rare cases the delta values can be much larger - up to 1440 for Chrome and up to 60 in FF. So a simple heuristic that looks at the range of values to detect Windows doesn't work. I am not sure why 99% of the time the values for FF and Chrome are 6,12 or 240 then they occasionally change dramatically - this looks like bugs in the browsers to me.

On Windows 8 with IE 10, the test page (http://brandonaaron.github.io/jquery-mousewheel/test/) with Test2 generates values from 1 to 8 - so scrolling is slow, but not quite as bad as Firefox/Chrome. I also see the same behavior with FF 25 on Windows 8 that I saw on XP. So it seems that the real difference is between OSX and Windows - and then on Windows each browser does different scaling.

k1w1 commented 11 years ago

Here is the fix I am experimenting with. It is crude, but seems to work pretty well across the browsers I have tested. Note that it keeps the normalization unchanged - in fact the normalization is essential to make the scrolling consistent on Windows.

    ....

    // Get a whole value for the deltas
    fn = delta > 0 ? 'floor' : 'ceil';
    delta  = Math[fn](delta / lowestDelta);
    deltaX = Math[fn](deltaX / lowestDeltaXY);
    deltaY = Math[fn](deltaY / lowestDeltaXY);

    // On windows, use a constant factor to speed up scrolling.
    if (isWin) {
      delta *= 20;
      deltaX *= 20;
      deltaY *= 20;
    }

    ...

where isWin is defined earlier:

var isWin = navigator.platform.indexOf("Win") != -1;
brandonaaron commented 11 years ago

I haven't had the time to experiment with it yet but I was thinking about passing along another param to the event handler that would be the factor (or lowestDelta). This would in theory provide the necessary information to know the resolution of the device being used. Actually, perhaps "resolution" is a better term for it.

The actual "resolution" is going to vary wildly depending on user setting and platform/device configurations. For instance users can change how many lines are scrolled and the acceleration on some operating systems and even per some browsers. Some configurations will show a dramatic acceleration rate such as OS X using a track pad.

By exposing the "resolution" then in theory one could decide how far to scroll for that particular users setup.

I'm leaning more towards an overhaul of the naming convention as a whole now. Change delta to velocity and introduce "resolution".

I think the next step really here is to gather the data points. Need to build a test page that logs and saves the information about the browser/os, the highest/lowest delta values, etc.

brandonaaron commented 11 years ago

Didn't mean to close it! Got click happy.

brandonaaron commented 11 years ago

To help understand the data better for everyone I built a quick app that shows the normalized delta, raw delta, and resolution. Hit a few browser/os/device combinations (be sure to reload if you switch between different mice/trackpads/etc) and submit the results. http://mousewheeldatacollector.herokuapp.com/

brandonaaron commented 11 years ago

Here are some data points I got all on Mac OS X 10.9

Trackpad Safari (7.0.0) 1, 3 89, 267 3 Firefox (24.0.0) 1, 1 68, 68 1 Chrome (30.0.1599) 1, 3 175, 525 3

Traditional mouse wheel Firefox (24.0.0) 1, 0.100006103515625 203, 20.301239013671875 0.100006103515625 Safari (7.0.0) 1, 12 330, 3960 12 Chrome (30.0.1599) 1, 120 18, 2160 120

brandonaaron commented 11 years ago

Ok so here is the deal. I believe there are two primary use-cases in regards to this delta discussion.

The second use-case of emulating the default behavior is the difficult one to manage here. We don't know if the user is using a track pad or a mouse wheel or even if they've overwritten their settings. They might have the mouse wheel configured to actually act as a page down/up feature. So, emulating is hard. However, the current normalizing code can still help us developers guess at how far the user is expecting to scroll if I expose the "resolution" or what is called the lowestDelta in the current code. That value can be used to multiply the provided normalized delta to see how far the user might want to scroll. This still won't be 100% reliable though but should work for the emulating behavior.

The normalized delta value really helps the first use case of changing the mouse wheel behavior entirely. It gives a consistent result in all browsers despite what settings the user has. The only caveat to this is when the user switches between devices (trackpad, regular mouse wheel) in the same page session. The trackpad generally has a very small resolution while the regular mouse wheel typically has a higher resolution.

mattdw commented 11 years ago

Hey @brandonaaron, thanks for this lib. I'm currently using it on a project which needs pretty uniform and robust scrolling speeds, so I've been hacking on the normalisation and lucked onto an approach I'd be interested to get some feedback on.

I'm seeing a couple of limitations in the current approach:

As a result I was seeing everything from [1,1,1,1,1,…] to [1,2,128,1440,900,320,4,1,1] with the current normalisation, which is pretty hard to turn into a consistent UX.

What I'm doing instead is tracking a cumulative average of all scroll deltas seen so far, and returning delta / cumulative_average. It has the same "confused by multiple devices" problem that your current approach has (although it would eventually correct itself), and it takes the first few scroll events to calibrate itself, but has the big advantages of (a) being self-calibrating over time and (b) eventually returning a distribution centered around 1.0 for all cases (I think; I haven't charted it).

In practice, I'm not seeing any weirdness on the first few scrolls; I suspect because scroll events seem to come in a bunch at a time, and individual events each have quite a small effect, so any crazy numbers quickly get smoothed out. On the downside, it's unlikely to have any direct connection to 'screen pixels scrolled'.

I'm happy to fork/pull request/whatever if you're interested in this approach, but in the meantime the key piece of code (replacing the calculations of only lowestDelta for this example) is:

at line 24, where lowestDelta is declared, add:

var averageDelta = 0, eventCount = 0;

then on line 104 and following:

  // Look for lowest delta to normalize the delta values
  absDelta = Math.abs(delta);

+ averageDelta = (absDelta + (averageDelta * eventCount)) / (eventCount + 1);
+ eventCount += 1;
+ 
+ delta = delta / averageDelta;

I'd be keen to hear your thoughts.

brandonaaron commented 11 years ago

@mattdw Interesting idea! Any chance I could see exactly how you are using it for your project?

I implemented your change locally to the mouse wheel data collection app real quick to see the results side-by-side. The distance from zero is certainly less with this method. However, this does create an interesting instability because a single, identical scroll action will hold many different values. For example if I just go one click slowly on my mouse wheel I'll get 1 every time. But once I scroll a little faster (to create a higher delta) the same one click now has a value < 1. If I scroll really fast and then normal or slow again... the value is really, really small.

brandonaaron commented 11 years ago

Side note: I completely forgot we can get the delta mode (pixels, lines, or pages) from the event. It is event.deltaMode. http://www.w3.org/TR/DOM-Level-3-Events/#widl-WheelEvent-deltaMode Wish I would have incorporated that into the mouse wheel data collection app in the first pass.

mattdw commented 11 years ago

The project is not yet public, so I don't have anything to show at the moment sorry! I'm basically doing cross-platform inertial scrubbing of a video, set up so it feels like you're moving down a page. A consistent "feel" (acceleration, velocity, etc) is more important in my case than mapping pixels to pixels.

And agreed, the numbers aren't perfect, but they do balance out over time, and in the aggregate seem to work pretty evenly (e.g. because a bunch of events are sent, the average/center is more important than the value of any given event.) Obviously this is not the case with very fine one-click-at-a-time scrolling; I have wondered about taking the square root to dampen the distribution too, but probably that's something that should happen in user code.

How widely supported would event.deltaMode be? It should be relatively easy to get a line-height from the document and convert back to pixels, too? (The real win of this library for me is that it, much like jQuery, papers over browser differences in a useful way.)

brandonaaron commented 11 years ago

I'm experimenting with trying to emulate the native scrolling behavior in a new branch called "distance" ( https://github.com/brandonaaron/jquery-mousewheel/tree/distance ). After some trial and error with the math, I came up with something that is pretty close when using the mouse wheel but is a bit too fast with the trackpad. Feel free to checkout this branch and attempt to fix my math because I really don't know what I'm doing there. Relevant line: https://github.com/brandonaaron/jquery-mousewheel/blob/distance/examples/scrolling/index.html#L45

brandonaaron commented 10 years ago

This is now resolved in 3.1.6. Please use the event.deltaX, event.deltaY, and event.deltaFactor properties. Better yet, checkout the 4.0.x branch and use the very latest which brings the delta signs in line with the new wheel event standard.