对于一个不同的问题,我撰写了此答案,包括此示例代码 。
在该代码中,我使用鼠标滚轮放大/缩小 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
我可以使用什么代码在 Chrome v10/11、Firefox v4、Safari v5、Opera v11 和 IE9 上滚动相同数量的鼠标滚轮来获得相同的“增量”值?
此问题相关,但有没有好的答案。
编辑:进一步调查显示,一个滚动事件“向上”是:
| 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 触控板,即使缓慢移动也会产生不同的结果:
- 在 Safari 和 Chrome 上,鼠标滚轮的
wheelDelta
值为 3,而不是 120。
- 在 Firefox 上,
detail
通常是 2
,有时是 1
,但是当滚动非常缓慢时根本没有事件处理程序触发 。
所以问题是:
区分这种行为的最佳方法是什么(最好没有任何用户代理或操作系统嗅探)?
For a different question I composed this answer, including this sample code.
In that code I use the mouse wheel to zoom in/out of an HTML5 Canvas. I found some code that normalizes speed differences between Chrome and Firefox. However, the zoom handling in Safari is much, much faster than in either of those.
Here's the code I currently have:
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
What code can I use to get the same 'delta' value for the same amount of mouse wheel rolling across Chrome v10/11, Firefox v4, Safari v5, Opera v11 and IE9?
This question is related, but has no good answer.
Edit: Further investigation shows that one scroll event 'up' is:
| 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
Further, using the MacBook trackpad on OS X gives different results even when moving slowly:
- On Safari and Chrome, the
wheelDelta
is a value of 3 instead of 120 for mouse wheel.
- On Firefox the
detail
is usually 2
, sometimes 1
, but when scrolling very slowly NO EVENT HANDLER FIRES AT ALL.
So the question is:
What is the best way to differentiate this behavior (ideally without any user agent or OS sniffing)?
发布评论
评论(10)
绝对没有简单的方法可以在所有浏览器中的所有操作系统中的所有用户之间进行标准化。
它比你列出的变体更糟糕 - 在我的 WindowsXP+Firefox3.6 设置上,我的鼠标滚轮每一级滚动 6 次 - 可能是因为我忘记在某个地方我加速了鼠标滚轮,无论是在操作系统中还是在大约的某个地方: 然而,
我正在解决类似的问题(顺便说一句,使用类似的应用程序,但非画布),并且通过仅使用 +1 / -1 的 delta 符号并随着时间的推移进行测量,我就遇到了这个问题上次发射时,您将获得加速度,即。如果有人滚动一次与在几分钟内滚动多次(我敢打赌谷歌地图就是这样做的)。
这个概念在我的测试中似乎效果很好,只需将任何小于 100 毫秒的时间添加到加速中即可。
There is definitely no simple way to normalize across all users in all OS in all browsers.
It gets worse than your listed variations - on my WindowsXP+Firefox3.6 setup my mousewheel does 6 per one-notch scroll - probably because somewhere I've forgotten I've accelerated the mouse wheel, either in the OS or somewhere in about:config
However I am working on a similar problem (with a similar app btw, but non-canvas) and it occurs to me by just using the delta sign of +1 / -1 and measuring over time the last time it fired, you'll have a rate of acceleration, ie. if someone scrolls once vs several times in a few moments (which I would bet is how google maps does it).
The concept seems to work well in my tests, just make anything less than 100ms add to the acceleration.
编辑 2014 年 9 月
鉴于:
......我只能推荐使用这个简单的,基于符号的-计数代码:
最初的正确尝试如下。
这是我第一次尝试使用脚本来规范化值。它在 OS X 上有两个缺陷:OS X 上的 Firefox 将生成应有值的 1/3,而 OS X 上的 Chrome 将生成应有值的 1/40。
您可以在自己的浏览器上测试此代码: http://phrogz.net/JS/wheeldelta.html
欢迎提出检测和改进 OS X 上 Firefox 和 Chrome 行为的建议。
编辑:@Tom 的一项建议是将每个事件调用简单地计为单次移动,使用距离的符号来调整它。这不会在 OS X 上的平滑/加速滚动下产生很好的结果,也不会在鼠标滚轮移动非常快时(例如
wheelDelta
为 240)完美处理情况,但这种情况很少发生。由于此处描述的原因,该代码现在是本答案顶部显示的推荐技术。Edit September 2014
Given that:
…I can only recommend using this simple, sign-based-counting code:
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.
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.我们 Facebook 的朋友为这个问题提出了一个很好的解决方案。
我已经在使用 React 构建的数据表上进行了测试,它像黄油一样滚动!
该解决方案适用于各种浏览器、Windows/Mac,并且都使用触控板/鼠标。
源代码可以在这里找到:https://github。 com/facebook/fixed-data-table/blob/master/src/vendor_upstream/dom/normalizeWheel.js
Our friends at Facebook put together a great solution to this problem.
I have tested on a data table that I'm building using React and it scrolls like butter!
This solution works on a variety of browsers, on Windows/Mac, and both using trackpad/mouse.
The source code can be found here: https://github.com/facebook/fixed-data-table/blob/master/src/vendor_upstream/dom/normalizeWheel.js
这是我疯狂地尝试生成一个跨浏览器连贯且规范化的 delta (-1 <= delta <= 1 ) :
这完全是经验性的,但在 Safari 6、FF 16、Opera 12 (OS X) 和 IE 上效果很好XP 上为 7
Here is my crazy attempt to produce a cross browser coherent and normalized delta ( -1 <= delta <= 1 ) :
This is totally empirical but works quite good on Safari 6, FF 16, Opera 12 (OS X) and IE 7 on XP
我制作了一个表格,其中包含不同事件/浏览器返回的不同值, 考虑到某些浏览器已经支持的 DOM3
wheel
事件(下表)。基于此,我创建了这个函数来标准化速度:
http://jsfiddle.net/mfe8J/1/
mousewheel
、wheel
和DOMMouseScroll
事件表:I made a table with different values returned by different events/browsers, taking into account the DOM3
wheel
event that some browsers already support (table under).Based on that I made this function to normalize the speed:
http://jsfiddle.net/mfe8J/1/
Table for
mousewheel
,wheel
andDOMMouseScroll
events:另一个或多或少的独立解决方案……
这并不需要在事件之间考虑时间。一些浏览器似乎总是用相同的三角洲发射事件,然后快速滚动时更快地发射它们。其他人确实改变了三角洲。可以想象一个需要时间的自适应标准器,但这会在某种程度上参与其中和尴尬。
在这里可用的工作: jsbin/iqafek/2
Another more or less self-contained solution...
This doesn't take time between events into account though. Some browsers seem to always fire events with the same delta, and just fire them faster when scrolling quickly. Others do vary the deltas. One can imagine an adaptive normalizer that takes time into account, but that'd get somewhat involved and awkward to use.
Working available here: jsbin/iqafek/2
简单且可行的解决方案:
Simple and working solution:
这是我今天困扰了几个小时的问题,而且不是第一次了:(
我一直在尝试通过“滑动”来总结值,并查看不同浏览器如何报告值,它们差异很大,Safari 在几乎所有平台上报告的数量级都更大,Chrome 报告的数量比 firefox 多得多(比如 3 倍),firefox 从长远来看是平衡的,但在小幅变化的平台之间差异很大(在 Ubuntu gnome 上,几乎只 + 3或-3,似乎它总结了较小的事件,然后发送一个大的“+3”)
目前找到的解决方案有三个:
中的想法很好,并且有效,并且是我唯一的解决方案。目前发现跨浏览器完全一致。
不幸的是,它也倾向于重新标准化加速度。如果您尝试(在他们的演示中),并以最大速度上下滚动一段时间,您会发现极快或极慢的滚动基本上会产生几乎相同的移动量。相反,如果您重新加载页面并且仅非常缓慢地滑动,您会发现它会滚动得非常快”。
这对于习惯在触摸板上进行剧烈滚动滑动并期望得到结果的 Mac 用户(例如我)来说是令人沮丧的 。
更重要的是,由于它会根据获得的最大值来降低鼠标速度,因此用户尝试加快速度的次数越多,速度就会减慢得越多,而“缓慢滚动” 用户将体验到相当快的速度。
这使得这个(否则很出色)解决方案成为解决方案 1 的更好的实现。
我将该解决方案移植到了 jquery mousewheel 插件:http://jsfiddle.net/SimoneGianni/pXzVv/
如果您使用它一段时间,您会发现您将开始获得相当均匀的结果,但是您会还注意到它倾向于很快地+1/-1值,
我现在正在努力增强它以更好地检测峰值,这样它们就不会发送“超出范围”的所有内容。最好还获得 0 到 1 之间的浮点值作为增量值,以便有一致的输出。
This is a problem I've been fighting with for some hours today, and not for the first time :(
I've been trying to sum up values over a "swipe" and see how different browsers report values, and they vary a lot, with Safari reporting order of magnitude bigger numbers on almost all platforms, Chrome reporting quite more (like 3 times more) than firefox, firefox being balanced on the long run but quite different among platforms on small movements (on Ubuntu gnome, nearly only +3 or -3, seems like it sums up smaller events and then send a big "+3")
The current solutions found right now are three :
The idea in Qooxdoo is good, and works, and is the only solution I've currently found to be completely consistent cross browser.
Unfortunately it tends to renormalize also the acceleration. If you try it (in their demos), and scroll up and down at maximum speed for a while, you'll notice that scrolling extremely fast or extremely slow basically produce nearly the same amount of movement. On the opposite if you reload the page and only swipe very slowly, you'll notice that it will scroll quite fast".
This is frustrating for a Mac user (like me) used to give vigorous scroll swipes on the touchpad and expecting to get to the top or bottom of the scrolled thing.
Even more, since it scales down the mouse speed based on the maximum value obtained, the more your user tries to speed it up, the more it will slow down, while a "slow scrolling" user will experience quite fast speeds.
This makes this (otherwise brilliant) solution a slightly better implementation of solution 1.
I ported the solution to the jquery mousewheel plugin : http://jsfiddle.net/SimoneGianni/pXzVv/
If you play with it for a while, You'll see that you'll start getting quite homogeneous results, but you'll also notice that it tend to +1/-1 values quite fast.
I'm now working on enhancing it to detect peaks better, so that they don't send everything "out of scale". It would also be nice to also obtain a float value between 0 and 1 as the delta value, so that there is a coherent output.
要在触摸设备上支持缩放,请注册gesturestart、gesturechange和gestureend事件并使用event.scale属性。您可以看到 示例代码。
对于 Firefox 17,桌面版和移动版计划支持
onwheel
事件(根据 onwheel 上的 MDN 文档)。另外,对于 Firefox,也许 Gecko 特定的MozMousePixelScroll
事件很有用(尽管现在可能已弃用该事件,因为 DOMMouseWheel 事件现已在 Firefox 中弃用)。对于 Windows,驱动程序本身似乎会生成 WM_MOUSEWHEEL、WM_MOUSEHWHEEL 事件(也许还生成用于触摸板平移的 WM_GESTURE 事件?)。这可以解释为什么 Windows 或浏览器似乎没有标准化鼠标滚轮事件值本身(并且可能意味着您无法编写可靠的代码来标准化这些值)。
对于
onwheel
(不是 onmousewheel)事件在 Internet Explorer 中支持 IE9 和 IE10,您还可以使用 W3C 标准onwheel
事件。然而,一个档位可以是不同于 120 的值(例如,在我的鼠标上,一个档位变为 111(而不是 -120)使用此测试页面)。我写了另一篇文章,其中包含可能相关的其他详细轮子事件。基本上,在我自己对滚轮事件的测试中(我试图标准化滚动的值),我发现我得到了不同的操作系统、浏览器供应商、浏览器版本、事件类型和设备(Microsoft 倾斜滚轮鼠标、笔记本电脑触摸板手势)的值、带滚动区的笔记本电脑触摸板、Apple 魔术鼠标、Apple 强大的鼠标滚动球、Mac 触摸板等)。
并且必须忽略浏览器配置(例如 Firefox mousewheel.enable_pixel_scrolling、chrome --scroll-pixels=150)、驱动程序设置(例如 Synaptics 触摸板)和操作系统配置(Windows 鼠标设置、OSX 鼠标首选项、 X.org 按钮设置)。
For zoom support on touch devices, register for the gesturestart, gesturechange and gestureend events and use the event.scale property. You can see example code for this.
For Firefox 17 the
onwheel
event is planned to be supported by desktop and mobile versions (as per MDN docs on onwheel). Also for Firefox maybe the Gecko specificMozMousePixelScroll
event is useful (although presumably this is now deprecated since the DOMMouseWheel event is now deprecated in Firefox).For Windows, the driver itself seems to generate the WM_MOUSEWHEEL, WM_MOUSEHWHEEL events (and maybe the WM_GESTURE event for touchpad panning?). That would explain why Windows or the browser doesn't seem to normalise the mousewheel event values itself (and might mean you cannot write reliable code to normalise the values).
For
onwheel
(not onmousewheel) event support in Internet Explorer for IE9 and IE10, you can also use the W3C standardonwheel
event. However one notch can be a value different from 120 (e.g. a single notch becomes 111 (instead of -120) on my mouse using this test page). I wrote another article with other details wheel events that might be relevant.Basically in my own testing for wheel events (I am trying to normalise the values for scrolling), I have found that I get varying values for OS, browser vendor, browser version, event type, and device (Microsoft tiltwheel mouse, laptop touchpad gestures, laptop touchpad with scrollzone, Apple magic mouse, Apple mighty mouse scrollball, Mac touchpad, etc etc).
And have to ignore a variety of side-effects from browser configuration (e.g. Firefox mousewheel.enable_pixel_scrolling, chrome --scroll-pixels=150), driver settings (e.g. Synaptics touchpad), and OS configuration (Windows mouse settings, OSX Mouse preferences, X.org button settings).