Edit September 2014
Given that:
- Different versions of the same browser on OS X have yielded different values in the past, and may do so in the future, and that
- Using the trackpad on OS X yields very similar effects to using a mouse wheel, yet gives very different event values, and yet the device difference cannot be detected by JS
…I can only recommend using this simple, sign-based-counting code:
var handleScroll = function(evt){
if (!evt) evt = event;
var direction = (evt.detail<0 || evt.wheelDelta>0) ? 1 : -1;
// Use the value as you will
};
someEl.addEventListener('DOMMouseScroll',handleScroll,false); // for Firefox
someEl.addEventListener('mousewheel', handleScroll,false); // for everyone else
Original attempt to be correct follows.
Here is my first attempt at a script to normalize the values. It has two flaws on OS X: Firefox on OS X will produce values 1/3 what they should be, and Chrome on OS X will produce values 1/40 what they should be.
// Returns +1 for a single wheel roll 'up', -1 for a single roll 'down'
var wheelDistance = function(evt){
if (!evt) evt = event;
var w=evt.wheelDelta, d=evt.detail;
if (d){
if (w) return w/d/40*d>0?1:-1; // Opera
else return -d/3; // Firefox; TODO: do not /3 for OS X
} else return w/120; // IE/Safari/Chrome TODO: /3 for Chrome OS X
};
You can test out this code on your own browser here: http://phrogz.net/JS/wheeldelta.html
Suggestions for detecting and improving the behavior on Firefox and Chrome on OS X are welcome.
Edit: One suggestion from @Tom is to simply count each event call as a single move, using the sign of the distance to adjust it. This will not give great results under smooth/accelerated scrolling on OS X, nor handle perfectly cases when the mouse wheel is moved very fast (e.g. wheelDelta
is 240), but these happen infrequently. This code is now the recommended technique shown at the top of this answer, for the reasons described there.
The Qt Documentation elaborates a bit more on why it is actually 120:
QPoint QWheelEvent::angleDelta() const
Returns the distance that the wheel is rotated, in eighths of a degree. A
positive value indicates that the wheel was rotated forwards away from the
user; a negative value indicates that the wheel was rotated backwards toward
the user.
Most mouse types work in steps of 15 degrees, in which case the delta value is
a multiple of 120; i.e., 120 units * 1/8 = 15 degrees.
However, some mice have finer-resolution wheels and send delta values that are
less than 120 units (less than 15 degrees). To support this possibility, you
can either cumulatively add the delta values from events until the value of 120
is reached, then scroll the widget, or you can partially scroll the widget in
response to each wheel event.
https://doc.qt.io/qt-5/qwheelevent.html#angleDelta
Best Answer
You should be able to handle the PreviewMouseWheel event. The delta for each event will be +/-120, but you will get one event for each "notch" of the wheel.