我正在使用以下事件侦听器来检测鼠标滚轮和滚动方向:
window.addEventListener('wheel', ({ deltaY }) => {
console.log(deltaY);
if (deltaY > 0) scrollDown();
else if (deltaY < 0) scrollUp();
});
在这里发生以下情况:
deltaY
由于滚动加速度计而不断记录scrollDown()
或scrollUp()
持续发射直到加速度计停止我只想在每次用户互动时触发一次scrollUp
和scrollDown
。因此,我需要检测一个新鼠标滚动事件,而不是每个鼠标滚动事件。这可能吗?
我确实尝试过超时,以检测deltaY
是否由于加速度计而仍在变化,但这还不够,因为如果仍在变化,第二次用户交互不会触发scrollUp
或scrollDown
。
以下是我要实现的CodePen:https://codepen.io/anon/pen/dQmPNN
它非常接近必需的功能,但是如果您在第一张幻灯片上用力敲击鼠标滚轮,然后尝试立即滚动到下一张幻灯片,则超时解决方案将其锁定,因此您必须等待另一秒钟左右,直到超时完成,您可以继续滚动。
答案 0 :(得分:0)
您是否尝试过使用标志将其分解为功能以检查是否发生了交互?
例如:
// Create a global variable which will keep track of userInteraction
let shouldScroll = true;
// add the event listener, and call the function when triggered
window.addEventListener('wheel', () => myFunction());
//Create a trigger function, checking if shouldScroll is true or false.
myFunction(){
shouldScroll ? (
if (deltaY > 0) scrollDown();
else if (deltaY < 0) scrollUp();
// Change back to false to prevent further scrolling.
shouldScroll = false;
) : return;
}
/* call this function when user interaction occurs
and you want to allow scrolling function again.. */
userInteraction(){
// set to true to allow scrolling
shouldScroll = true;
}
答案 1 :(得分:0)
我们可以通过延迟执行并消除延迟之间的事件来避免这种情况,请参见以下示例,并添加了1000ms作为延迟,可以根据您的要求进行修改。
let scrollPage = (deltaY)=>{
console.log(deltaY);
if (deltaY > 0) scrollDown();
else if (deltaY < 0) scrollUp();
};
var delayReg;
window.addEventListener('wheel', ({ deltaY }) => {
clearTimeout(delayReg);
delayReg = setTimeout(scrollPage.bind(deltaY),1000);
});
答案 2 :(得分:0)
这是旧的,但是我在寻找几乎相同问题的答案时发现了。 我已出于我的目的解决了该问题,因此,这是我的解决方案,以防万一。
问题实际上是定义什么才算是一个连续动作。如果没有更具体的工作要解决,那只是时间问题。这是事件之间的时间是关键-因此算法是不断累积事件,直到它们之间有一定的差距。接下来剩下的就是弄清楚允许的间隙应该有多大,这是特定于解决方案的。这就是用户停止滚动直到获得反馈后的最大延迟。我的最佳时间是四分之一秒,下面将其用作默认值。
下面是我的JavaScript,我使用jQuery将事件附加到ID为“ wheelTestDiv”的div上,但它与window对象的作用相同,如问题所示。
值得注意的是,以下内容会寻找任何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>