web-dev-qa-db-ja.com

jquery mousewheel:ホイールがいつ停止するかを検出しますか?

Jquery mousewheel プラグインを使用していますが、ユーザーがホイールの使用を終了したことを検出できるようにしたいと思います。ドラッグ可能なもののstop:イベントと同様の機能。誰かが私を正しい方向に向けることができますか?

20
Moustard

ここには実際には「停止」イベントはありません。doスクロールするとイベントが発生するため、マウスホイールイベントが発生するたびにイベントがトリガーされます...何もない場合、イベントは発生せず、ハンドラーは起動しません。

ただし、次のように、ユーザーが250ミリ秒以内に使用していないことを検出できます。

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

ここで試してみることができます 、以前にもう一度使用した場合は、使用するたびにタイムアウトを保存するだけです $.data() その時間がなくなると、クリアされます...実行したいコードが起動しない場合、ユーザーはテストしている期間にかかわらず、マウスホイールの使用を「終了」しています。

37
Nick Craver

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);
});

スクロール出力:

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!
9
abernier

ネイティブ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
2
Ryan Weiss

独自のホイールストップイベントを実装する方法は次のとおりです。

//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;

wheelstopイベントの新しいeventListenerを作成します

normalWheelEventCallbackFunction()から呼び出します

var wheelstop = new Event("wheelstop");

次に、このイベントがディスパッチされた場合のコールバックを定義してから、イベントをウィンドウオブジェクトに追加します。

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

ここで、通常のホイールイベントリスナーを定義し、このリスナーが使用するコールバックを定義します...

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

ホイールイベントコールバック関数

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;
}

これにはいくつかの間違いがあるかもしれませんが、ほとんどの場合、ロジックはかなり健全です。ただし、「wheelstop」イベントがディスパッチされた後に発生する可能性があるため、ディスパッチされたすべてのホイールイベントをキャッチする必要がある場合はフォールバックをお勧めします。

ああ、最後に、クリックイベントによって中断されてホイールイベントが終了した場合のハンドラーを実装してください...

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

Nick Craverの answer 正常に動作します。ただし、// do somethingの実行には(250ミリ秒の)わずかな遅延が発生します。より良いオプションは、コードをすぐに実行し、delayms待ってからさらにイベントをキャッチすることです。

これを行うには、processingなどのグローバル変数を使用し、falseで初期化し、コード実行の前後で値を切り替えます。

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.
   }
 });
0
musafar006