javascript 车轮事件PreventDefault不会取消车轮事件

bihw5rsg  于 2022-12-21  发布在  Java
关注(0)|答案(4)|浏览(189)

我希望每个滚动事件仅获得一个事件
我尝试这个代码,但它产生“轮”,因为多次轮事件被触发。任何帮助?谢谢

window.addEventListener("wheel",
    (e)=> {
        console.log("wheel");
        e.preventDefault();
    },
    {passive:false}
    );

用例(编辑)我希望仅允许在页面之间滚动-滚动时带有动画。一旦检测到onwheel事件,我希望在动画完成之前停止它,否则前一个onwheel事件将继续触发,并被视为新事件,因此转到目标页面的下一个
我的结论:无法取消滚轮事件。为了在旋转事件(来自先前用户动作)正在进行时识别新的用户滚轮动作,我们需要计算此类事件的速度/加速度

deyfvvtc

deyfvvtc1#

这是一个相当简单的问题,存储在任何地方的最后一个方向,并有条件地执行您的代码:

direction = '';
window.addEventListener('wheel',  (e) => {
    if (e.deltaY < 0) {
      //scroll wheel up
      if(direction !== 'up'){
        console.log("up");
        direction = 'up';
      }
    }
    if (e.deltaY > 0) {
      //scroll wheel down
      if(direction !== 'down'){
        console.log("down");
        direction = 'down';
      }
    }
  });

无论如何,UX上下文应该被定义。在某些情况下,* 节流 * 或 * 去抖动 * 您的函数可能会给予更好的结果。

节流

节流强制了函数在一段时间内可以被调用的最大次数。如“最多每100毫秒执行一次此函数”。

消除抖动

去抖强制一个函数在一定时间内不再被调用。如“只有在100毫秒内没有被调用时才执行此函数。
在您的情况下,也许 * 去抖动 * 是最好的选择。

暂时锁定浏览器滚动条

x一个一个一个一个x一个一个二个x

643ylb08

643ylb082#

你几乎就有了,但是你需要把你的代码 Package 在一个函数中。我添加了一些额外的小位,这样你就可以区分上下了:)

//scroll wheel manipulation
  window.addEventListener('wheel', function (e) {
    //TODO add delay
    if (e.deltaY < 0) {
      //scroll wheel up
      console.log("up");
    }
    if (e.deltaY > 0) {
      //scroll wheel down
      console.log("down");
    }
  });

它是如何工作的?

  • *(e)**=这只是一个事件,当你上下滚动时,这个函数会被触发,但是没有函数事件,它就不知道该做什么!通常人们会写"事件",但是我很懒。
    • deltaY**=这是滚轮滚动的函数,它只是确保你沿着Y轴滚动。这是一个标准的内置函数,没有外部变量需要添加。

临时演员

setTimeout

你可以像@Lonnie Best建议的那样,在if语句中添加这个

4nkexdtk

4nkexdtk3#

您可以设置一个最小时间量,该时间量必须在您将其他滚动事件视为可操作事件之前经过。
例如,在下面的示例中,滚动事件之间必须经过3秒才能再次触发console.log("wheel")

function createScrollEventHandler(milliseconds)
{
  let allowed = true;
  return (event)=>
  {
        event.preventDefault();
        if (allowed)
        {
          console.log("wheel");
          allowed = false;
          setTimeout(()=>
          {
            allowed = true;
          },milliseconds);
        }  
  }
}
let scrollEventHandler = createScrollEventHandler(3000); // 3 seconds
window.addEventListener("wheel",scrollEventHandler);
gblwokeq

gblwokeq4#

Event.preventDefault()告知浏览器不要对该事件执行默认的预定义操作,例如导航到某个页面或提交包含的表单等。它不一定会阻止事件触发。
此外,wheel eventscroll event之间也有区别,用户旋转滚轮按钮时会触发wheel事件,而目标的scrollTopscrollLeft属性由于滚动位置更改而更改时会触发scroll事件。
当用户旋转滚轮按钮时,wheel事件将在 * 可以激发 * 的任何scroll事件之前激发。但是,wheel事件可能不会导致任何scroll事件,这仅仅是因为指针未悬停在任何元素上,或者元素此时不可滚动。
要将快速重复的函数调用聚合到事件处理程序,您可以debounce事件处理程序函数。**其思想是在提交操作之前等待一定的时间。**当函数被去抖时,它将成为一个新函数,当被调用时,设置一个定时器,调用内部的 Package 函数。当去抖函数被再次调用时,定时器被重置并重新启动。请看下面的示例图。
版权所有Ilya Kantor(https://javascript.info/,现代JavaScript教程)
函数f是一个去抖函数,超时持续时间为1000ms,分别在0、200ms和500ms时刻调用,参数为abc。由于f是去抖函数,调用f(a)f(b)"未提交/忽略",因为在1000ms持续时间内存在对f的另一调用。呼叫f(c)在时刻1500ms被"提交/接受",因为在1000ms内没有进一步的呼叫跟随。
要实现这一点,可以使用setTimeoutclearTimeout函数。setTimeout函数接受一个操作(要执行的代码或函数)和以毫秒为单位的延迟,然后返回一个整数形式的计时器ID。当计时器到期时,给定的操作将被执行,而不会被取消。

const timerId = setTimeout(action, delay)

然后可以使用clearTimeout函数销毁具有给定ID的计时器。

clearTimeout(timerId)

可以使用以下简单的去抖动实现:

// Default timeout is set to 1000ms
function debounce(func, timeout = 1000) {
    // A slot to save timer id for current debounced function
    let timer
    // Return a function that conditionally calls the original function
    return (...args) => {
        // Immediately cancel the timer when called
        clearTimeout(timer)
        // Start another timer that will call the original function
        // unless canceled by following call
        timer = setTimeout(() => {
            // Pass all arguments and `this` value
            func.apply(this, args)
        }, timeout)
    }
}

了解更多信息:Default parametersRest parametersFunction.apply()this keyword
使用起来相当简单:

eventTarget.addEventListener('wheel', debounce((e) => {
    console.log('wheel', e)
}))

这将把console.log调用限制为只要wheel事件在一秒钟内未被激发。
示例:

function debounce(f, d = 99, t) {
    return (...a) => {
        clearTimeout(t)
        t = setTimeout(() => {
            f.apply(this, a)
        }, d)
    }
}

document.addEventListener('wheel', debounce((_) => {
    console.log('wheel')
}))

A more modern approach在此基础上使用了Promise

相关问题