jquery mousewheel:检测滚轮何时停止?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3515446/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 15:35:16  来源:igfitidea点击:

jquery mousewheel: detecting when the wheel stops?

jqueryevent-handlingmousewheel

提问by Moustard

I'm using Jquery mousewheelplugin and I would like like to be able to detect when the user has finished using the wheel. Similar functionality as the stop: event in the draggable stuff. Can somebody point me to the right direction?

我正在使用 Jquery鼠标滚轮插件,我希望能够检测到用户何时使用完滚轮。与可拖动内容中的 stop: 事件类似的功能。有人可以指出我正确的方向吗?

回答by Nick Craver

There's no "stop" event here really - you get an event when you doscroll, so every time a mousewheel event happens the event is triggered...when there's nothing you'll get no events and your handler won't be firing.

这里真的没有“停止”事件 - 当你滚动时你得到一个事件,所以每次发生鼠标滚轮事件时都会触发该事件......

You ca however detect when the user hasn't used it in say 250ms, like this:

但是,您可以检测用户在 250 毫秒内未使用它的时间,如下所示:

$("#myElem").mousewheel(function() {
  clearTimeout($.data(this, 'timer'));
  $.data(this, 'timer', setTimeout(function() {
     alert("Haven't scrolled in 250ms!");
     //do something
  }, 250));
});

You can give it a try here, all we're doing is storing the timeout on each use in using $.data(), if you use it again before that time runs out, it gets cleared...if not then whatever code you wanted to run fires, the user has "finished" using their mousewheel for whatever period of time you're testing for.

您可以在这里尝试一下,我们所做的就是在 using 中存储每次使用的超时时间$.data(),如果您在该时间用完之前再次使用它,它将被清除......如果没有,那么您想要运行的任何代码都会触发,用户在您测试的任何时间段内都“完成”了使用他们的鼠标滚轮。

回答by abernier

To complete Nick Craver's answer:

要完成 Nick Craver 的回答:

var wheeldelta = {
  x: 0,
  y: 0
};
var wheeling;
$('#foo').on('mousewheel', function (e) {
  if (!wheeling) {
    console.log('start wheeling!');
  }

  clearTimeout(wheeling);
  wheeling = setTimeout(function() {
    console.log('stop wheeling!');
    wheeling = undefined;

    // reset wheeldelta
    wheeldelta.x = 0;
    wheeldelta.y = 0;
  }, 250);

  wheeldelta.x += e.deltaFactor * e.deltaX;
  wheeldelta.y += e.deltaFactor * e.deltaY;
  console.log(wheeldelta);
});

scrolling outputs:

滚动输出:

start wheeling!
Object {x: -1, y: 0}
Object {x: -36, y: 12}
Object {x: -45, y: 12}
Object {x: -63, y: 12}
Object {x: -72, y: 12}
Object {x: -80, y: 12}
Object {x: -89, y: 12}
Object {x: -97, y: 12}
Object {x: -104, y: 12}
Object {x: -111, y: 12}
Object {x: -117, y: 12}
Object {x: -122, y: 12}
Object {x: -127, y: 12}
Object {x: -131, y: 12}
Object {x: -135, y: 12}
Object {x: -139, y: 12}
Object {x: -145, y: 12}
Object {x: -148, y: 12}
Object {x: -152, y: 12}
Object {x: -154, y: 12}
Object {x: -156, y: 12}
Object {x: -157, y: 12}
Object {x: -158, y: 12}
Object {x: -159, y: 12}
Object {x: -161, y: 12}
Object {x: -162, y: 12}
Object {x: -164, y: 12}
Object {x: -166, y: 12}
Object {x: -167, y: 12}
Object {x: -169, y: 12}
stop wheeling!

回答by Ryan Weiss

Here's how to do it in native JavaScript:

以下是如何在原生 JavaScript 中执行此操作:

var _scrollTimeout = null;

function onMouseWheel() {
    var d = ((typeof e.wheelDelta != "undefined") ? (-e.wheelDelta) : e.detail);
    d = 100 * ((d>0)?1:-1);

    console.log("Scroll delta", d);

    clearTimeout(_scrollTimeout);
    _scrollTimeout = setTimeout(function() {
        console.log("Haven't scrolled in 250ms");
    }, 250);
}

window.addEventListener( 'mousewheel', onMouseWheel, false );
window.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox

回答by Brandon Roberts

Here's how to implement your own wheel stop event.

以下是如何实现您自己的车轮停止事件。

//initialise the new variables
var wheelMap = new Map;
var deltaXEnded = false;
var deltaYEnded = false;
var previousSwipe = Object;
    previousSwipe.timeStamp = 0;
    previousSwipe.deltaX = 0;
    previousSwipe.deltaY = 0;
var wheelstart = false;

make a new eventListener for the wheelstopevent

which we will be calling from the normalWheelEventCallbackFunction()

wheelstop事件创建一个新的事件监听器

我们将从normalWheelEventCallbackFunction()调用

var wheelstop = new Event("wheelstop");

next we will define the callback in the case of this event being dispatched & then add the event to the window object.

接下来,我们将在调度此事件的情况下定义回调,然后将事件添加到 window 对象。

function wheelstopcallback(event){
    wheelstart = false;
    console.log("wheel event has ended");
}
window.addEventListener("wheelstop", wheelstopcallback.bind(this));

now we define the normal wheel event listener as well as define the callback this listener will be using...

现在我们定义普通的轮事件侦听器以及此侦听器将使用的回调...

window.addEventListener("wheel", normalWheelEventCallbackFunction.bind(this));

The Wheel Event Callback Function

Wheel 事件回调函数

function normalWheelEventCallbackFunction(event){
   if(previousSwipe.timeStamp !== 0){
      if(event.timeStamp - previousSwipe.timeStamp < 1000)
         wheelMap.set(event.timeStamp, event);
      else
         wheelMap.clear();
   }
 else{previousSwipe.timeStamp = event.timeStamp;}


  if(event.deltaX > 2 && event.deltaX > previousSwipe.deltaX){
     //forward
     wheelstart = true
  }
  else if(event.deltaX < -2&& event.deltaX < previousSwipe.deltaX){
     //backward
     wheelstart = true;
  }
  else if(event.deltaY > 2 && event.deltaY > previousSwipe.deltaY){
     wheelstart = true;
  }
  else if(event.deltaY < 2 && event.deltaY < previousSwipe.deltaY){
     wheelstart = true;
  }

  if(
     ((event.deltaX === 1 || event.deltaX === 0 || event.deltaX === -1) && ((event.deltaX > 0 && event.deltaX < previousSwipe.deltaX) || (event.deltaX < 0 && event.deltaX > previousSwipe.deltaX)) && wheelstart)
     || (wheelstart && (event.deltaX === 0 && previousSwipe.deltaX === 0))
  )
  {
     deltaXEnded = true;
     console.log("deltaXEnded");
  }
  if(
     (((event.deltaY === 1 || event.deltaY === 0 || event.deltaY === -1) && ((event.deltaY > 0 && event.deltaY < previousSwipe.deltaY) || (event.deltaY < 0 && event.deltaY > previousSwipe.deltaY))) && wheelstart)
     || (wheelstart && (event.deltaY === 0 && previousSwipe.deltaY === 0)))     {
        deltaYEnded = true;
        console.log("deltaYEnded");
     }

     if(deltaXEnded && deltaYEnded){
        deltaXEnded = false;
        deltaYEnded = false;
        window.dispatchEvent(wheelstop);
     }

  previousSwipe.deltaX = event.deltaX;
  previousSwipe.deltaY = event.deltaY;
}

this may have a few mistakes, but for the most part the logic is pretty sound, I would recommend a fallback however if you are required to catch every single wheel event dispatched since it may have some after the 'wheelstop' event has been dispatched.

oh and lastly be sure and implement a handler for if it is interrupted by the click event which consequently ends the wheel event...

这可能有一些错误,但在大多数情况下,逻辑非常合理,我建议您使用回退,但是如果您需要捕获调度的每个单轮事件,因为在调度 'wheelstop' 事件之后可能会有一些。

哦,最后确定并实现一个处理程序,如果它被点击事件中断,从而结束轮子事件......

function wheelstopdispatch(){
  if(wheelstart)
    window.dispatchEvent(wheelstop);
  }
window.addEventListener("click", wheelstopdispatch);

回答by musafar006

Nick Craver's answerworks fine. But it will cause a small delay (of 250ms) to perform the // do something. A better option would be to execute your codes right away and wait delayms before catching further events.

尼克克雷弗的回答工作正常。但是它会导致一个小的延迟(250ms)来执行// do something. 更好的选择是立即执行您的代码并delay在捕获更多事件之前等待ms。

To do this, use a global variable say processing, initialize it with falseand toggle it's value before and after code execution.

为此,请使用全局变量 say processingfalse在代码执行之前和之后对其进行初始化并切换其值。

window.processing = false;
$("#myElem").mousewheel(function() {
   if (processing === false) {
     processing = true;
     // do something
     setTimeout(function() {
       processing = false;
     }, 250)); // waiting 250ms to change back to false.
   }
 });