将 Edge/IE JavaScript WheelEvent 增量转换为本机滚动量?

Converting Edge/IE JavaScript WheelEvent deltas to native scroll amounts?

在 Edge 和 Internet Explorer 中,我注意到一个奇怪的问题,即滚轮事件不等于其预期的滚动量。尽管 deltaMode 值被报告为 DOM_DELTA_PIXEL (0),但在 deltaY 中找到的像素数大于在小可滚动中实际滚动的像素数div.

以这段代码为例:

<!DOCTYPE html>
<html>
    <head>
        <title>test</title>
        <style>
        #scroller {
            width: 200px;
            height: 200px;
            overflow: scroll;
        }
        </style>
    </head>
    <body>
        <div id="scroller">
            <p>test</p><p>test</p><p>test</p><p>test</p>
            <p>test</p><p>test</p><p>test</p><p>test</p>
            <p>test</p><p>test</p><p>test</p><p>test</p>
        </div>
        <script>
(function() {'use strict';
    var scroller = document.getElementById('scroller');
    scroller.addEventListener('wheel', function(e) {
        var scrollY = e.deltaY;
        console.log('scrollY:', scrollY);
        setTimeout(function() {
            console.log('scroller.scrollTop:', scroller.scrollTop);
        }, 250);
    });
})();
        </script>
    </body>
</html>

在控制台中我看到这样的值:

scrollY: 101.8499984741211
scroller.scrollTop: 28

在 Chrome 等其他浏览器中,这些值匹配或至少非常接近。

因此实际滚动的数量与报告的数量不同。这是为什么,能不能得到正确的值?

值不同的原因是因为 IE 和 Edge 实际上根据 window 滚动区域所占的比例缩小 DOM 像素。

这会使计算浏览器的适当缩放变得复杂,并且由于 IE/Edge 是唯一这样做的,您将不得不使用某种形式的用户代理嗅探。

要获得正确的滚动量,您需要将 deltaY 乘以 (scroller.clientHeight / window.innerHeight)deltaX 也是如此)。

这是经过这些调整后的同一样本:

<!DOCTYPE html>
<html>
    <head>
        <title>test</title>
        <style>
        #scroller {
            width: 200px;
            height: 200px;
            overflow: scroll;
        }
        </style>
    </head>
    <body>
        <div id="scroller">
            <p>test</p><p>test</p><p>test</p><p>test</p>
            <p>test</p><p>test</p><p>test</p><p>test</p>
            <p>test</p><p>test</p><p>test</p><p>test</p>
        </div>
        <script>
(function() {
    'use strict';
    var scroller = document.getElementById('scroller');
    scroller.addEventListener('wheel', function(e) {
        var deltaY = e.deltaY;
        var scaleY = scroller.clientHeight / window.innerHeight;
        var scrollY = deltaY * scaleY;
        console.log('scrollY:', scrollY);
        setTimeout(function() {
            console.log('scroller.scrollTop:', scroller.scrollTop);
        }, 250);
    });
})();
        </script>
    </body>
</html>

这在我的控制台中给出了以下输出:

scrollY: 28.199999577518067
scroller.scrollTop: 28

请注意 scrollTop 值没有浮点数,因此如果您希望值完全匹配,可以 Math.round 它们。