-
-
Save xiel/09db10ba6fb5280d48c90e693cff0863 to your computer and use it in GitHub Desktop.
Facebook attempt at normalizing wheel event
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Copyright (c) 2015, Facebook, Inc. | |
* All rights reserved. | |
* | |
* This source code is licensed under the BSD-style license found in the | |
* LICENSE file in the root directory of this source tree. An additional grant | |
* of patent rights can be found in the PATENTS file in the same directory. | |
* | |
* @providesModule normalizeWheel | |
* @typechecks | |
*/ | |
'use strict'; | |
var UserAgent_DEPRECATED = require('UserAgent_DEPRECATED'); | |
var isEventSupported = require('isEventSupported'); | |
// Reasonable defaults | |
var PIXEL_STEP = 10; | |
var LINE_HEIGHT = 40; | |
var PAGE_HEIGHT = 800; | |
/** | |
* Mouse wheel (and 2-finger trackpad) support on the web sucks. It is | |
* complicated, thus this doc is long and (hopefully) detailed enough to answer | |
* your questions. | |
* | |
* If you need to react to the mouse wheel in a predictable way, this code is | |
* like your bestest friend. * hugs * | |
* | |
* As of today, there are 4 DOM event types you can listen to: | |
* | |
* 'wheel' -- Chrome(31+), FF(17+), IE(9+) | |
* 'mousewheel' -- Chrome, IE(6+), Opera, Safari | |
* 'MozMousePixelScroll' -- FF(3.5 only!) (2010-2013) -- don't bother! | |
* 'DOMMouseScroll' -- FF(0.9.7+) since 2003 | |
* | |
* So what to do? The is the best: | |
* | |
* normalizeWheel.getEventType(); | |
* | |
* In your event callback, use this code to get sane interpretation of the | |
* deltas. This code will return an object with properties: | |
* | |
* spinX -- normalized spin speed (use for zoom) - x plane | |
* spinY -- " - y plane | |
* pixelX -- normalized distance (to pixels) - x plane | |
* pixelY -- " - y plane | |
* | |
* Wheel values are provided by the browser assuming you are using the wheel to | |
* scroll a web page by a number of lines or pixels (or pages). Values can vary | |
* significantly on different platforms and browsers, forgetting that you can | |
* scroll at different speeds. Some devices (like trackpads) emit more events | |
* at smaller increments with fine granularity, and some emit massive jumps with | |
* linear speed or acceleration. | |
* | |
* This code does its best to normalize the deltas for you: | |
* | |
* - spin is trying to normalize how far the wheel was spun (or trackpad | |
* dragged). This is super useful for zoom support where you want to | |
* throw away the chunky scroll steps on the PC and make those equal to | |
* the slow and smooth tiny steps on the Mac. Key data: This code tries to | |
* resolve a single slow step on a wheel to 1. | |
* | |
* - pixel is normalizing the desired scroll delta in pixel units. You'll | |
* get the crazy differences between browsers, but at least it'll be in | |
* pixels! | |
* | |
* - positive value indicates scrolling DOWN/RIGHT, negative UP/LEFT. This | |
* should translate to positive value zooming IN, negative zooming OUT. | |
* This matches the newer 'wheel' event. | |
* | |
* Why are there spinX, spinY (or pixels)? | |
* | |
* - spinX is a 2-finger side drag on the trackpad, and a shift + wheel turn | |
* with a mouse. It results in side-scrolling in the browser by default. | |
* | |
* - spinY is what you expect -- it's the classic axis of a mouse wheel. | |
* | |
* - I dropped spinZ/pixelZ. It is supported by the DOM 3 'wheel' event and | |
* probably is by browsers in conjunction with fancy 3D controllers .. but | |
* you know. | |
* | |
* Implementation info: | |
* | |
* Examples of 'wheel' event if you scroll slowly (down) by one step with an | |
* average mouse: | |
* | |
* OS X + Chrome (mouse) - 4 pixel delta (wheelDelta -120) | |
* OS X + Safari (mouse) - N/A pixel delta (wheelDelta -12) | |
* OS X + Firefox (mouse) - 0.1 line delta (wheelDelta N/A) | |
* Win8 + Chrome (mouse) - 100 pixel delta (wheelDelta -120) | |
* Win8 + Firefox (mouse) - 3 line delta (wheelDelta -120) | |
* | |
* On the trackpad: | |
* | |
* OS X + Chrome (trackpad) - 2 pixel delta (wheelDelta -6) | |
* OS X + Firefox (trackpad) - 1 pixel delta (wheelDelta N/A) | |
* | |
* On other/older browsers.. it's more complicated as there can be multiple and | |
* also missing delta values. | |
* | |
* The 'wheel' event is more standard: | |
* | |
* http://www.w3.org/TR/DOM-Level-3-Events/#events-wheelevents | |
* | |
* The basics is that it includes a unit, deltaMode (pixels, lines, pages), and | |
* deltaX, deltaY and deltaZ. Some browsers provide other values to maintain | |
* backward compatibility with older events. Those other values help us | |
* better normalize spin speed. Example of what the browsers provide: | |
* | |
* | event.wheelDelta | event.detail | |
* ------------------+------------------+-------------- | |
* Safari v5/OS X | -120 | 0 | |
* Safari v5/Win7 | -120 | 0 | |
* Chrome v17/OS X | -120 | 0 | |
* Chrome v17/Win7 | -120 | 0 | |
* IE9/Win7 | -120 | undefined | |
* Firefox v4/OS X | undefined | 1 | |
* Firefox v4/Win7 | undefined | 3 | |
* | |
*/ | |
function normalizeWheel(/*object*/ event) /*object*/ { | |
var sX = 0, sY = 0, // spinX, spinY | |
pX = 0, pY = 0; // pixelX, pixelY | |
// Legacy | |
if ('detail' in event) { sY = event.detail; } | |
if ('wheelDelta' in event) { sY = -event.wheelDelta / 120; } | |
if ('wheelDeltaY' in event) { sY = -event.wheelDeltaY / 120; } | |
if ('wheelDeltaX' in event) { sX = -event.wheelDeltaX / 120; } | |
// side scrolling on FF with DOMMouseScroll | |
if ( 'axis' in event && event.axis === event.HORIZONTAL_AXIS ) { | |
sX = sY; | |
sY = 0; | |
} | |
pX = sX * PIXEL_STEP; | |
pY = sY * PIXEL_STEP; | |
if ('deltaY' in event) { pY = event.deltaY; } | |
if ('deltaX' in event) { pX = event.deltaX; } | |
if ((pX || pY) && event.deltaMode) { | |
if (event.deltaMode == 1) { // delta in LINE units | |
pX *= LINE_HEIGHT; | |
pY *= LINE_HEIGHT; | |
} else { // delta in PAGE units | |
pX *= PAGE_HEIGHT; | |
pY *= PAGE_HEIGHT; | |
} | |
} | |
// Fall-back if spin cannot be determined | |
if (pX && !sX) { sX = (pX < 1) ? -1 : 1; } | |
if (pY && !sY) { sY = (pY < 1) ? -1 : 1; } | |
return { spinX : sX, | |
spinY : sY, | |
pixelX : pX, | |
pixelY : pY }; | |
} | |
/** | |
* The best combination if you prefer spinX + spinY normalization. It favors | |
* the older DOMMouseScroll for Firefox, as FF does not include wheelDelta with | |
* 'wheel' event, making spin speed determination impossible. | |
*/ | |
normalizeWheel.getEventType = function() /*string*/ { | |
return (UserAgent_DEPRECATED.firefox()) | |
? 'DOMMouseScroll' | |
: (isEventSupported('wheel')) | |
? 'wheel' | |
: 'mousewheel'; | |
}; | |
module.exports = normalizeWheel; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment