将 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
它们。
在 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
它们。