现代浏览器中的鼠标滚轮事件

79

我希望有一个干净漂亮的JavaScript鼠标滚轮事件,仅支持最新版本的常见浏览器,不需要为过时版本编写遗留代码,也不需要任何JS框架。

鼠标滚轮事件在 这里 得到了很好的解释。如何简化它以适应当前最新版本的浏览器?

我无法测试所有浏览器,所以 caniuse.com 对我来说是个很好的帮助。可惜的是,鼠标滚轮事件在那里没有提到。

基于 Derek 的评论,我写了这个解决方案。这对所有浏览器都有效吗?

someObject.addEventListener("onwheel" in document ? "wheel" : "mousewheel", function(e) {
  e.wheel = e.deltaY ? -e.deltaY : e.wheelDelta/40;
  // custom code
});

3
Chrome和IE支持MouseWheelEvent,而Firefox支持WheelEvent。要跨浏览器监听,请参见这里 - Derek 朕會功夫
1
补充Derek的观点。在这些情况下,您应该真正评估浏览器的兼容性。您可以使用Modernizr(http://www.modernizr.com)来完成这项工作。它会让您的生活变得更加轻松 :) - user1467267
4
现在,根据MDN的说法,所有现代桌面浏览器都支持wheel事件。 - gdros
3个回答

106

简洁明了:

window.addEventListener("wheel", event => console.info(event.deltaY));

浏览器可能会返回不同的delta值(例如,Chrome返回+120(向上滚动)或-120(向下滚动)。将其标准化的一个好技巧是提取其符号,从而将其有效地转换为+1/-1

window.addEventListener("wheel", event => {
    const delta = Math.sign(event.deltaY);
    console.info(delta);
});

参考资料: MDN.


2
我更喜欢保持wheelDelta的绝对值以检测滚动速度。有没有公式可以在各种浏览器中进行规范化? - Jan Turoň
很遗憾,如果你想使用绝对值,没有公式可用。你必须依靠某种表格来获取每个浏览器/操作系统组合的经验值。对于普通鼠标,wheelDelta始终固定,无论你滚动得有多快,所以可以按照我上面提出的方法进行操作。然而,如果你想捕捉轨迹板的灵敏度(我猜这就是你要找的),那么你就得自己摸索了。让我们希望这个值在未来能够在各个浏览器中得到标准化。 - Lucio Paiva
1
这确实会在控制台中触发警告:[Violation] Added non-passive event listener to a scroll-blocking 'wheel' event. Consider marking event handler as 'passive' to make the page more responsive. See https://www.chromestatus.com/feature/5745543795965952 - Derk Jan Speelman
有趣。我使用的是 Chrome 68,没有看到这个提示。@DerkJanSpeelman 你确定你在测试与上面完全相同的代码吗? 我刚刚尝试了两个版本(带和不带 delta 符号提取),但无法复现你看到的问题。 - Lucio Paiva
1
我这里仍然无法重现。也许是因为不同的操作系统?我正在尝试在Ubuntu 18.04上运行。此外,您是否同时运行任何额外的代码?无论如何,MDN提到通过向addEventListener()传递第三个参数{passive:true}可以解决问题,如果您不需要event.preventDefault()。如果确实需要,看起来没有太多可做的(请检查评论中的抱怨)。 - Lucio Paiva
显示剩余5条评论

58

这里有一篇文章描述了这个问题,并且给出了一个例子:

http://www.sitepoint.com/html5-javascript-mouse-wheel/

相关代码,不包括调整图像大小的具体示例:

var myitem = document.getElementById("myItem");
if (myitem.addEventListener)
{
    // IE9, Chrome, Safari, Opera
    myitem.addEventListener("mousewheel", MouseWheelHandler, false);
    // Firefox
    myitem.addEventListener("DOMMouseScroll", MouseWheelHandler, false);
}
// IE 6/7/8
else
{
    myitem.attachEvent("onmousewheel", MouseWheelHandler);
}

function MouseWheelHandler(e)
{
    // cross-browser wheel delta
    var e = window.event || e; // old IE support
    var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail)));

    return false;
}

1
优秀的回答。需要更多关注。在这个问题上有许多不完整的答案。 - Terrance00
这似乎是一个已弃用的事件,并已从许多浏览器中删除。现在要使用的事件是“WheelEvent”(https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent)。 - dug
这对于旧浏览器的支持很有用,特别是IE根本不支持Math.sign,但是支持Math.max和Math.min。https://caniuse.com/?search=Math.sign - ryancdotnet

8
这个在Firefox、Chrome和Edge中也可以工作:
window.addEventListener("wheel", function(e) {
    var dir = Math.sign(e.deltaY);
    console.log(dir);
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接