这是旧的,但我在寻找几乎相同问题的答案时发现了它。
我为自己的目的解决了这个问题,所以这是我的解决方案,以防它帮助其他人。
真正的问题在于定义什么是一个连续的动作。如果没有更具体的工作,这只是时间问题。关键是事件之间的时间 - 所以算法是不断累积事件,直到它们之间存在一定的差距。然后剩下的就是弄清楚允许的差距应该有多大,这是特定于解决方案的。这就是用户停止滚动直到他们得到反馈后的最大延迟。我的最佳值是四分之一秒,我在下面使用它作为默认值。
下面是我的 JavaScript,我正在使用 jQuery 将事件附加到 id 为“wheelTestDiv”的 div,但它与窗口对象的工作方式相同,如问题所示。
值得注意的是,下面会查找任何 onWheel 事件,但仅跟踪 Y 轴。如果您需要更多轴,或者只想在 deltaY 发生更改时将事件计数到计时器中,则需要适当地更改代码。
另外值得注意的是,如果您不需要针对不同 DOM 对象跟踪事件的灵活性,您可以将类重构为具有静态方法和属性,因此无需创建全局对象变量。如果您确实需要跟踪不同的 DOM 对象(我需要),那么您可能需要该类的多个实例。
"use strict";
class MouseWheelAggregater {
// Pass in the callback function and optionally, the maximum allowed pause
constructor(func, maxPause) {
this.maxAllowedPause = (maxPause) ? maxPause : 250; // millis
this.last = Date.now();
this.cummulativeDeltaY = 0;
this.timer;
this.eventFunction = func;
}
set maxPause(pauseTime) {
this.maxAllowedPause = pauseTime;
}
eventIn(e) {
var elapsed = Date.now() - this.last;
this.last = Date.now();
if ((this.cummulativeDeltaY === 0) || (elapsed < this.maxAllowedPause)) {
// Either a new action, or continuing a previous action with little
// time since the last movement
this.cummulativeDeltaY += e.originalEvent.deltaY;
if (this.timer !== undefined) clearTimeout(this.timer);
this.timer = setTimeout(this.fireAggregateEvent.bind(this),
this.maxAllowedPause);
} else {
// just in case some long-running process makes things happen out of
// order
this.fireAggregateEvent();
}
}
fireAggregateEvent() {
// Clean up and pass the delta to the callback
if (this.timer !== undefined) clearTimeout(this.timer);
var newDeltaY = this.cummulativeDeltaY;
this.cummulativeDeltaY = 0;
this.timer = undefined;
// Use a local variable during the call, so that class properties can
// be reset before the call. In case there's an error.
this.eventFunction(newDeltaY);
}
}
// Create a new MouseWheelAggregater object and pass in the callback function,
// to call each time a continuous action is complete.
// In this case, just log the net movement to the console.
var mwa = new MouseWheelAggregater((deltaY) => {
console.log(deltaY);
});
// Each time a mouse wheel event is fired, pass it into the class.
$(function () {
$("#wheelTestDiv").on('wheel', (e) => mwa.eventIn(e));
});
网页 ...
<!DOCTYPE html>
<html>
<head>
<title>Mouse over test</title>
<script src="/mouseWheelEventManager.js"></script>
</head>
<body>
<div id="wheelTestDiv" style="margin: 50px;">Wheel over here</div>
</body>
</html>