webentwicklung-frage-antwort-db.com.de

jQuery-Mausrad: Erkennen, wann das Rad stoppt?

Ich verwende Jquery mousewheel plugin und möchte erkennen können, wenn der Benutzer das Rad nicht mehr verwendet. Ähnliche Funktionalität wie das stop: -Ereignis im Drag & Drop-Bereich. Kann mich jemand in die richtige Richtung weisen?

20
Moustard

Hier gibt es wirklich kein "Stopp" -Ereignis - Sie erhalten ein Ereignis, wenn Sie do scrollen, sodass jedes Mal, wenn ein Mausradereignis eintritt, das Ereignis ausgelöst wird ... wenn es nichts gibt, erhalten Sie keine Ereignisse und Ihren Handler wird nicht schießen.

Sie können jedoch feststellen, wenn der Benutzer es in sagen wir 250 ms nicht verwendet hat, wie folgt:

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

Sie können es hier ausprobieren , wir speichern das Timeout nur bei jeder Verwendung von $.data() . Wenn Sie es vor Ablauf dieser Zeit erneut verwenden, wird es gelöscht ... if nicht dann, welcher Code Sie auch immer auslösen wollten, der Benutzer hat sein Mausrad für den Zeitraum, auf den Sie testen, "fertiggestellt".

36
Nick Craver

Um die Antwort von Nick Craver zu vervollständigen:

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-Ausgänge:

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

So implementieren Sie Ihr eigenes Radstopp-Ereignis.

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

erstelle einen neuen eventListener für das wheelstop event

was wir von der normalWheelEventCallbackFunction () aufrufen werden

var wheelstop = new Event("wheelstop");

als Nächstes definieren wir den Rückruf für den Fall, dass dieses Ereignis ausgelöst wird, und fügen dann das Ereignis zum Fensterobjekt hinzu.

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

jetzt definieren wir den normalen Rad-Ereignis-Listener sowie den Rückruf, den dieser Listener verwenden wird ...

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

Die Wheel Event Callback Funktion

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

dies mag ein paar Fehler haben, aber die Logik ist größtenteils ziemlich gut. Ich würde jedoch einen Fallback empfehlen, wenn Sie jedes einzelne ausgelöste Radereignis abfangen müssen, da es nach dem Auslösen des Ereignisses 'Wheelstop' einige haben kann.

oh und zum Schluss stellen Sie sicher und implementieren Sie einen Handler für den Fall, dass er durch das Klickereignis unterbrochen wird, das folglich das Radereignis beendet ...

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

Nick Cravers Antwort funktioniert gut. Aber es wird eine kleine Verzögerung (von 250 ms) verursachen, um den // do something auszuführen. Eine bessere Option wäre, Ihre Codes sofort auszuführen und delayms zu warten, bevor Sie weitere Ereignisse abfangen.

Verwenden Sie dazu eine globale Variable mit der Bezeichnung processing, initialisieren Sie sie mit false und ändern Sie den Wert vor und nach der Codeausführung.

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

So geht's in nativem 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
0
Ryan Weiss