Phr*_*ogz 139 javascript mousewheel
在该代码中,我使用鼠标滚轮来放大/缩小HTML5 Canvas.我找到了一些代码来规范Chrome和Firefox之间的速度差异.但是,Safari中的缩放处理要比其中任何一个快得多.
这是我目前的代码:
var handleScroll = function(e){
var delta = e.wheelDelta ? e.wheelDelta/40 : e.detail ? -e.detail/3 : 0;
if (delta) ...
return e.preventDefault() && false;
};
canvas.addEventListener('DOMMouseScroll',handleScroll,false); // For Firefox
canvas.addEventListener('mousewheel',handleScroll,false); // Everyone else
Run Code Online (Sandbox Code Playgroud)
在Chrome v10/11,Firefox v4,Safari v5,Opera v11和IE9上滚动相同数量的鼠标滚轮时,我可以使用哪些代码来获得相同的"delta"值?
这个问题是相关的,但没有好的答案.
编辑:进一步调查显示一个滚动事件'up'是:
| evt.wheelDelta | evt.detail ------------------+----------------+------------ Safari v5/Win7 | 120 | 0 Safari v5/OS X | 120 | 0 Safari v7/OS X | 12 | 0 Chrome v11/Win7 | 120 | 0 Chrome v37/Win7 | 120 | 0 Chrome v11/OS X | 3 (!) | 0 (possibly wrong) Chrome v37/OS X | 120 | 0 IE9/Win7 | 120 | undefined Opera v11/OS X | 40 | -1 Opera v24/OS X | 120 | 0 Opera v11/Win7 | 120 | -3 Firefox v4/Win7 | undefined | -3 Firefox v4/OS X | undefined | -1 Firefox v30/OS X | undefined | -1
此外,即使在缓慢移动时,在OS X上使用MacBook触控板也会产生不同的结果:
wheelDelta
鼠标滚轮的值为3而不是120.detail
通常是2
,有时1
,但是当滚动非常缓慢时,没有任何事情.所以问题是:
区分此行为的最佳方法是什么(理想情况下,没有任何用户代理或操作系统嗅探)?
Phr*_*ogz 53
编辑2014年9月
鉴于:
...我只能建议使用这个简单的,基于标志的计数代码:
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
Run Code Online (Sandbox Code Playgroud)
原始的尝试是正确的.
这是我第一次尝试使用脚本来规范化值.它在OS X上有两个缺陷:OS X上的Firefox将产生1/3的值,OS X上的Chrome将产生1/40的值.
// 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
};
Run Code Online (Sandbox Code Playgroud)
您可以在自己的浏览器上测试此代码:http://phrogz.net/JS/wheeldelta.html
欢迎在OS X上检测和改进Firefox和Chrome行为的建议.
编辑:@Tom的一个建议是简单地将每个事件调用计为一次移动,使用距离的符号进行调整.这在OS X上的平滑/加速滚动下不会给出很好的结果,也不能在鼠标滚轮移动得非常快时(例如wheelDelta
240)处理完美的情况,但这些情况很少发生.由于此处描述的原因,此代码现在是本答案顶部显示的推荐技术.
小智 28
这是我疯狂尝试生成跨浏览器相干和标准化增量(-1 <= delta <= 1):
var o = e.originalEvent,
d = o.detail, w = o.wheelDelta,
n = 225, n1 = n-1;
// Normalize delta
d = d ? w && (f = w/d) ? d/f : -d/1.35 : w/120;
// Quadratic scale if |d| > 1
d = d < 1 ? d < -1 ? (-Math.pow(d, 2) - n1) / n : d : (Math.pow(d, 2) + n1) / n;
// Delta *should* not be greater than 2...
e.delta = Math.min(Math.max(d / 2, -1), 1);
Run Code Online (Sandbox Code Playgroud)
这完全是经验性的,但在Safari 6,FF 16,Opera 12(OS X)和XP上的IE 7上运行良好
Geo*_*rge 21
我们在Facebook的朋友们为这个问题提供了一个很好的解决方案.
我已经在一个数据表上进行了测试,我正在使用React进行构建,它像黄油一样滚动!
此解决方案适用于各种浏览器,Windows/Mac和两者都使用触控板/鼠标.
// Reasonable defaults
var PIXEL_STEP = 10;
var LINE_HEIGHT = 40;
var PAGE_HEIGHT = 800;
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 };
}
Run Code Online (Sandbox Code Playgroud)
源代码可以在这里找到:https://github.com/facebook/fixed-data-table/blob/master/src/vendor_upstream/dom/normalizeWheel.js
Ser*_*gio 11
我创建了一个包含不同事件/浏览器返回的不同值的表,同时考虑到 wheel
某些浏览器已经支持的DOM3事件(表格下).
基于此,我使这个功能规范化速度:
function normalizeWheelSpeed(event) {
var normalized;
if (event.wheelDelta) {
normalized = (event.wheelDelta % 120 - 0) == -0 ? event.wheelDelta / 120 : event.wheelDelta / 12;
} else {
var rawAmmount = event.deltaY ? event.deltaY : event.detail;
normalized = -(rawAmmount % 3 ? rawAmmount * 10 : rawAmmount / 3);
}
return normalized;
}
Run Code Online (Sandbox Code Playgroud)
表mousewheel
,wheel
和DOMMouseScroll
事件:
| mousewheel | Chrome (win) | Chrome (mac) | Firefox (win) | Firefox (mac) | Safari 7 (mac) | Opera 22 (mac) | Opera 22 (win) | IE11 | IE 9 & 10 | IE 7 & 8 |
|-------------------|--------------|--------------|---------------|---------------|----------------|----------------|----------------|-----------|-------------|-----------|
| event.detail | 0 | 0 | - | - | 0 | 0 | 0 | 0 | 0 | undefined |
| event.wheelDelta | 120 | 120 | - | - | 12 | 120 | 120 | 120 | 120 | 120 |
| event.wheelDeltaY | 120 | 120 | - | - | 12 | 120 | 120 | undefined | undefined | undefined |
| event.wheelDeltaX | 0 | 0 | - | - | 0 | 0 | 0 | undefined | undefined | undefined |
| event.delta | undefined | undefined | - | - | undefined | undefined | undefined | undefined | undefined | undefined |
| event.deltaY | -100 | -4 | - | - | undefined | -4 | -100 | undefined | undefined | undefined |
| event.deltaX | 0 | 0 | - | - | undefined | 0 | 0 | undefined | undefined | undefined |
| | | | | | | | | | | |
| wheel | Chrome (win) | Chrome (mac) | Firefox (win) | Firefox (mac) | Safari 7 (mac) | Opera 22 (mac) | Opera 22 (win) | IE11 | IE 10 & 9 | IE 7 & 8 |
| event.detail | 0 | 0 | 0 | 0 | - | 0 | 0 | 0 | 0 | - |
| event.wheelDelta | 120 | 120 | undefined | undefined | - | 120 | 120 | undefined | undefined | - |
| event.wheelDeltaY | 120 | 120 | undefined | undefined | - | 120 | 120 | undefined | undefined | - |
| event.wheelDeltaX | 0 | 0 | undefined | undefined | - | 0 | 0 | undefined | undefined | - |
| event.delta | undefined | undefined | undefined | undefined | - | undefined | undefined | undefined | undefined | - |
| event.deltaY | -100 | -4 | -3 | -0,1 | - | -4 | -100 | -99,56 | -68,4 | -53 | - |
| event.deltaX | 0 | 0 | 0 | 0 | - | 0 | 0 | 0 | 0 | - |
| | | | | | | | | | | |
| | | | | | | | | | | |
| DOMMouseScroll | | | Firefox (win) | Firefox (mac) | | | | | | |
| event.detail | | | -3 | -1 | | | | | | |
| event.wheelDelta | | | undefined | undefined | | | | | | |
| event.wheelDeltaY | | | undefined | undefined | | | | | | |
| event.wheelDeltaX | | | undefined | undefined | | | | | | |
| event.delta | | | undefined | undefined | | | | | | |
| event.deltaY | | | undefined | undefined | | | | | | |
| event.deltaX | | | undefined | undefined | | | | | | |
Run Code Online (Sandbox Code Playgroud)
另一种或多或少的独立解决方案......
但是,事件之间不需要花费时间.有些浏览器似乎总是使用相同的delta来触发事件,并且在快速滚动时只需更快地触发它们.其他人确实改变了三角洲.人们可以想象一个需要花费时间的自适应规范化器,但这有点牵扯并且难以使用.
可在此处工作:jsbin/iqafek/2
var normalizeWheelDelta = function() {
// Keep a distribution of observed values, and scale by the
// 33rd percentile.
var distribution = [], done = null, scale = 30;
return function(n) {
// Zeroes don't count.
if (n == 0) return n;
// After 500 samples, we stop sampling and keep current factor.
if (done != null) return n * done;
var abs = Math.abs(n);
// Insert value (sorted in ascending order).
outer: do { // Just used for break goto
for (var i = 0; i < distribution.length; ++i) {
if (abs <= distribution[i]) {
distribution.splice(i, 0, abs);
break outer;
}
}
distribution.push(abs);
} while (false);
// Factor is scale divided by 33rd percentile.
var factor = scale / distribution[Math.floor(distribution.length / 3)];
if (distribution.length == 500) done = factor;
return n * factor;
};
}();
// Usual boilerplate scroll-wheel incompatibility plaster.
var div = document.getElementById("thing");
div.addEventListener("DOMMouseScroll", grabScroll, false);
div.addEventListener("mousewheel", grabScroll, false);
function grabScroll(e) {
var dx = -(e.wheelDeltaX || 0), dy = -(e.wheelDeltaY || e.wheelDelta || 0);
if (e.detail != null) {
if (e.axis == e.HORIZONTAL_AXIS) dx = e.detail;
else if (e.axis == e.VERTICAL_AXIS) dy = e.detail;
}
if (dx) {
var ndx = Math.round(normalizeWheelDelta(dx));
if (!ndx) ndx = dx > 0 ? 1 : -1;
div.scrollLeft += ndx;
}
if (dy) {
var ndy = Math.round(normalizeWheelDelta(dy));
if (!ndy) ndy = dy > 0 ? 1 : -1;
div.scrollTop += ndy;
}
if (dx || dy) { e.preventDefault(); e.stopPropagation(); }
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
65289 次 |
最近记录: |