Javascript 检测新的鼠标滚轮事件

Javascript 检测新的鼠标滚轮事件,javascript,mousewheel,Javascript,Mousewheel,我正在使用以下事件侦听器检测鼠标滚轮和滚动方向: window.addEventListener('wheel', ({ deltaY }) => { console.log(deltaY); if (deltaY > 0) scrollDown(); else if (deltaY < 0) scrollUp(); }); window.addEventListener('wheel',({deltaY})=>{ 控制台日志(deltaY); 如果(deltaY

我正在使用以下事件侦听器检测鼠标滚轮和滚动方向:

window.addEventListener('wheel', ({ deltaY }) => {
  console.log(deltaY);
  if (deltaY > 0) scrollDown();
  else if (deltaY < 0) scrollUp();
});
window.addEventListener('wheel',({deltaY})=>{
控制台日志(deltaY);
如果(deltaY>0)向下滚动();
否则如果(deltaY<0)向上滚动();
});
这里发生了以下情况:

  • Macbook上的双指触摸板滚动会触发事件处理程序
  • deltaY
    由于滚动加速度计而保持日志记录
  • scrollDown()
    scrollUp()
    持续启动,直到加速计停止
我只想在每个用户交互中启动一次
向上滚动
向下滚动
。因此,我需要检测新的鼠标滚动事件,而不是每个鼠标滚动事件。这可能吗

我确实尝试了一个超时来检测是否由于加速计的原因,
deltaY
仍在变化,但这还不够,因为如果加速计仍在变化,第二次用户交互不会触发
向上滚动
向下滚动

下面是我试图实现的一个代码笔:


它非常接近所需的功能,但是如果您在第一张幻灯片上用力敲击鼠标滚轮,然后尝试立即滚动到下一张幻灯片,超时解决方案会将其锁定,因此您必须再等待一秒钟左右,直到超时完成,然后才能继续滚动。

您是否尝试将其拆分为带有标志的函数,以检查是否发生了交互

例如:

// 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;
}
//创建一个全局变量,用于跟踪用户交互
让shouldcoll=true;
//添加事件侦听器,并在触发时调用该函数
addEventListener('wheel',()=>myFunction());
//创建一个触发器函数,检查shouldScroll是true还是false。
myFunction(){
应该滚动吗(
如果(deltaY>0)向下滚动();
否则如果(deltaY<0)向上滚动();
//更改回false以防止进一步滚动。
shouldcoll=false;
):返回;
}
/*当发生用户交互时调用此函数
您想再次允许滚动功能*/
用户交互(){
//设置为true以允许滚动
shouldcoll=true;
}

我们可以通过延迟执行和删除延迟之间的事件来避免这种情况,参考下面的示例,并添加了1000毫秒作为延迟,可以根据您的要求进行修改

        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);
        });
let scrollPage=(deltaY)=>{
控制台日志(deltaY);
如果(deltaY>0)向下滚动();
否则如果(deltaY<0)向上滚动();
};
var-delayReg;
addEventListener('wheel',({deltaY})=>{
clearTimeout(delayReg);
delayReg=setTimeout(scrollPage.bind(deltaY),1000);
});

这是一个古老的问题,但我在寻找几乎相同问题的答案时发现了它。 我解决这个问题是出于我的目的,所以这里是我的解决方案,以防它对其他人有帮助

问题是如何定义一个连续的动作。如果没有更具体的工作,这只是时间问题。关键是事件之间的时间,所以算法是不断累积事件,直到它们之间有一定的间隔。接下来剩下的就是计算出允许的差距应该有多大,这是解决方案特有的。这是用户停止滚动直到收到反馈后的最大延迟。我的最佳值是四分之一秒,我在下面的示例中将其用作默认值

下面是我的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));
});
“严格使用”;
类鼠标轮聚合器{
//传入回调函数和(可选)允许的最大暂停时间
构造函数(func、maxPause){
this.maxAllowedPause=(maxPause)?maxPause:250;//毫秒
this.last=Date.now();
this.cumulativedeltay=0;
这个计时器;
this.eventFunction=func;
}
设置最大暂停(暂停时间){
this.maxAllowedPause=pauseTime;
}
事件素(e){
var expead=Date.now()-this.last;
this.last=Date.now();
if((this.cumulativedeltay==0)| |(经过<!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>