Obtenir les événements de la molette de la souris dans jQuery?

130

Existe-t-il un moyen d'obtenir les événements de la molette de la souris (sans parler des scrollévénements) dans jQuery?

thejh
la source
1
Une recherche rapide a révélé ce plugin qui peut aider.
Jerad Rose
Cette solution fonctionne pour moi: stackoverflow.com/questions/7154967/jquery-detect-scrolldown
bertie
@thejh a publié une nouvelle réponse à ce sujet avec les événements DOM3: stackoverflow.com/a/24707712/2256325
Sergio
Juste une note à ce sujet. Si vous souhaitez simplement détecter les modifications apportées à une entrée et que celle-ci ne détecte pas les modifications via la molette de la souris, essayez$(el).on('input', ...
rybo111

Réponses:

46

Il existe un plugin qui détecte la molette de la souris haut / bas et la vitesse sur une région.

Darin Dimitrov
la source
35
brancher? allez .. vérifiez la réponse ci-dessous, vous pouvez le faire sans
201
$(document).ready(function(){
    $('#foo').bind('mousewheel', function(e){
        if(e.originalEvent.wheelDelta /120 > 0) {
            console.log('scrolling up !');
        }
        else{
            console.log('scrolling down !');
        }
    });
});
mahdi shahbazi
la source
51
L' DOMMouseScrollévénement est utilisé dans FF, vous devez donc écouter sur les deux .bind('DOMMouseScroll mousewheel') {evetns developer.mozilla.org/en-US/docs/DOM/DOM_event_reference
...
9
e.originalEvent.wheelDeltan'est pas défini dans FF23
hofnarwillie
26
Vous n'avez pas besoin de diviser par 120, c'est un gaspillage inutile de CPU
venimus
6
doit avoir été la meilleure réponse
2
Mais de toute façon, pourquoi voudriez-vous le diviser par 120? Quelle est cette constante? (Vous n'êtes pas obligé, comme l'a souligné Venimus.)
mshthn
145

Lié aux deux mousewheelet a DOMMouseScrollfini par fonctionner très bien pour moi:

$(window).bind('mousewheel DOMMouseScroll', function(event){
    if (event.originalEvent.wheelDelta > 0 || event.originalEvent.detail < 0) {
        // scroll up
    }
    else {
        // scroll down
    }
});

Cette méthode fonctionne dans IE9 +, Chrome 33 et Firefox 27.


Edit - mars 2016

J'ai décidé de revenir sur cette question depuis un certain temps. La page MDN pour l'événement de défilement a un excellent moyen de récupérer la position de défilement qui l'utilise requestAnimationFrame, ce qui est hautement préférable à ma méthode de détection précédente. J'ai modifié leur code pour offrir une meilleure compatibilité en plus de la direction et de la position du défilement:

(function() {
  var supportOffset = window.pageYOffset !== undefined,
    lastKnownPos = 0,
    ticking = false,
    scrollDir,
    currYPos;

  function doSomething(scrollPos, scrollDir) {
    // Your code goes here...
    console.log('scroll pos: ' + scrollPos + ' | scroll dir: ' + scrollDir);
  }

  window.addEventListener('wheel', function(e) {
    currYPos = supportOffset ? window.pageYOffset : document.body.scrollTop;
    scrollDir = lastKnownPos > currYPos ? 'up' : 'down';
    lastKnownPos = currYPos;

    if (!ticking) {
      window.requestAnimationFrame(function() {
        doSomething(lastKnownPos, scrollDir);
        ticking = false;
      });
    }
    ticking = true;
  });
})();

Voir le Pen Vanilla JS Scroll Tracking par Jesse Dupuy ( @ blindside85 ) sur CodePen .

Ce code fonctionne actuellement dans Chrome v50, Firefox v44, Safari v9, and IE9+

Références:

Jesse Dupuy
la source
Cela a fonctionné le mieux pour moi. Cependant, ce script s'exécute par "clic" de la molette de défilement. Cela peut être difficile à utiliser pour certains scripts. Existe-t-il un moyen de traiter chaque événement de défilement comme une seule instance, au lieu d'exécuter le script par clic de molette de défilement?
invot
Pas spécialement. D'après ce que j'ai vu, de nombreuses personnes éviteront de s'occuper du suivi du défilement ou utiliseront une minuterie à la place (par exemple, vérifier la position de l'utilisateur sur la page toutes les x millisecondes, etc.). S'il existe une solution plus performante, je veux vraiment en savoir plus!
Jesse Dupuy
1
J'ai trouvé un moyen de le faire: stackoverflow.com/questions/23919035/…
invot
1
Merci pour la mise à jour. Pouvez-vous copier votre code dans votre réponse? Je ne sais jamais si codepen pourrait tomber un jour. C'est arrivé avant.
JDB se souvient encore de Monica le
2
@JesseDupuy, je voterais pour cette réponse, mais votre version mise à jour ne fonctionne pas si le document correspond à la vue ("width: 100vh; height: 100vh") ou obtient "overflow: hidden;". "window.addEventListener ('scroll', callback)" n'est pas la bonne réponse à "window.addEventListener ('mousewheel', callback)".
Daniel
45

À partir de maintenant en 2017, vous pouvez simplement écrire

$(window).on('wheel', function(event){

  // deltaY obviously records vertical scroll, deltaX and deltaZ exist too
  if(event.originalEvent.deltaY < 0){
    // wheeled up
  }
  else {
    // wheeled down
  }
});

Fonctionne avec Firefox 51, Chrome 56, IE9 + actuels

Louis Ameline
la source
37

Les réponses évoquant l'événement "mousewheel" font référence à un événement obsolète. L'événement standard est simplement "roue". Voir https://developer.mozilla.org/en-US/docs/Web/Reference/Events/wheel

Brian Di Palma
la source
20
J'ai essayé ces derniers et j'ai trouvé: "wheel" fonctionne dans Firefox et IE mais pas Chrome. "mousewheel" fonctionne dans Chrome et IE mais pas Firefox. "DOMMouseScroll" ne fonctionne que dans Firefox.
Curtis Yallop
1
Whoa, cela m'a fait gagner beaucoup de temps. Merci!
gustavohenke
3
On dirait que Chrome a ajouté la prise en charge de "wheel" en août 2013: code.google.com/p/chromium/issues/detail?id=227454
rstackhouse le
2
Safari ne prend toujours pas en charge l'événement de roue.
Thayne du
Comme la documentation dit, l' wheelévénement est pris en charge sur Edge pas ce IEqui est pas la même chose. CanIuse
Alex
16

Cela a fonctionné pour moi :)

 //Firefox
 $('#elem').bind('DOMMouseScroll', function(e){
     if(e.originalEvent.detail > 0) {
         //scroll down
         console.log('Down');
     }else {
         //scroll up
         console.log('Up');
     }

     //prevent page fom scrolling
     return false;
 });

 //IE, Opera, Safari
 $('#elem').bind('mousewheel', function(e){
     if(e.originalEvent.wheelDelta < 0) {
         //scroll down
         console.log('Down');
     }else {
         //scroll up
         console.log('Up');
     }

     //prevent page fom scrolling
     return false;
 });

de stackoverflow

Anjith KP
la source
14

Voici une solution vanille. Peut être utilisé dans jQuery si l'événement passé à la fonction est event.originalEventque jQuery rend disponible en tant que propriété de l'événement jQuery. Ou si à l'intérieur de la callbackfonction sous nous ajoutons avant la première ligne:event = event.originalEvent; .

Ce code normalise la vitesse / quantité de la roue et est positif pour ce qui serait un défilement vers l'avant dans une souris typique, et négatif dans un mouvement de roue arrière de la souris.

Démo: http://jsfiddle.net/BXhzD/

var wheel = document.getElementById('wheel');

function report(ammout) {
    wheel.innerHTML = 'wheel ammout: ' + ammout;
}

function callback(event) {
    var normalized;
    if (event.wheelDelta) {
        normalized = (event.wheelDelta % 120 - 0) == -0 ? event.wheelDelta / 120 : event.wheelDelta / 12;
    } else {
        var rawAmmount = event.deltaY ? event.deltaY : event.detail;
        normalized = -(rawAmmount % 3 ? rawAmmount * 10 : rawAmmount / 3);
    }
    report(normalized);
}

var event = 'onwheel' in document ? 'wheel' : 'onmousewheel' in document ? 'mousewheel' : 'DOMMouseScroll';
window.addEventListener(event, callback);

Il existe également un plugin pour jQuery, qui est plus détaillé dans le code et un peu plus de sucre: https://github.com/brandonaaron/jquery-mousewheel

Sergio
la source
8

Cela fonctionne dans les dernières versions de chaque IE, Firefox et Chrome.

$(document).ready(function(){
        $('#whole').bind('DOMMouseScroll mousewheel', function(e){
            if(e.originalEvent.wheelDelta > 0 || e.originalEvent.detail < 0) {
                alert("up");
            }
            else{
                alert("down");
            }
        });
    });
futuredayv
la source
5

J'étais coincé dans ce problème aujourd'hui et j'ai trouvé que ce code fonctionnait bien pour moi

$('#content').on('mousewheel', function(event) {
    //console.log(event.deltaX, event.deltaY, event.deltaFactor);
    if(event.deltaY > 0) {
      console.log('scroll up');
    } else {
      console.log('scroll down');
    }
});
Prafull Sharma
la source
4

utiliser ce code

 knob.bind('mousewheel', function(e){  
 if(e.originalEvent.wheelDelta < 0) {
    moveKnob('down');
  } else {
    moveKnob('up');
 }
  return false;
});
Bal mukund kumar
la source
0

ma combinaison ressemble à ceci. il s'estompe et s'estompe à chaque défilement vers le bas / vers le haut. sinon, vous devez faire défiler jusqu'à l'en-tête, pour faire fondre l'en-tête.

var header = $("#header");
$('#content-container').bind('mousewheel', function(e){
    if(e.originalEvent.wheelDelta > 0) {
        if (header.data('faded')) {
            header.data('faded', 0).stop(true).fadeTo(800, 1);
        }
    }
    else{
        if (!header.data('faded')) header.data('faded', 1).stop(true).fadeTo(800, 0);
    }
});

celui ci-dessus n'est pas optimisé pour le tactile / mobile, je pense que celui-ci le fait mieux pour tous les mobiles:

var iScrollPos = 0;
var header = $("#header");
$('#content-container').scroll(function () {

    var iCurScrollPos = $(this).scrollTop();
    if (iCurScrollPos > iScrollPos) {
        if (!header.data('faded')) header.data('faded', 1).stop(true).fadeTo(800, 0);

    } else {
        //Scrolling Up
        if (header.data('faded')) {
            header.data('faded', 0).stop(true).fadeTo(800, 1);
        }
    }
    iScrollPos = iCurScrollPos;

});
Thomas Hartmann
la source
0

Le plugin que @DarinDimitrov a publié jquery-mousewheel, est cassé avec jQuery 3+ . Il serait plus judicieux d'utiliser jquery-wheelce qui fonctionne avec jQuery 3+.

Si vous ne souhaitez pas utiliser la route jQuery, MDN met en garde contre l'utilisation de l' mousewheelévénement car il n'est pas standard et n'est pas pris en charge dans de nombreux endroits. Il indique plutôt que vous devez utiliser l' wheelévénement car vous obtenez beaucoup plus de spécificité sur ce que signifient exactement les valeurs que vous obtenez. Il est pris en charge par la plupart des principaux navigateurs.

Coburn
la source
0

Si vous utilisez le plugin jquery mousewheel mentionné , que diriez-vous d'utiliser le 2ème argument de la fonction de gestionnaire d'événements - delta:

$('#my-element').on('mousewheel', function(event, delta) {
    if(delta > 0) {
    console.log('scroll up');
    } 
    else {
    console.log('scroll down');
    }
});
Mojo
la source
-3

J'ai eu le même problème récemment où $(window).mousewheelrevenaitundefined

Ce que j'ai fait était $(window).on('mousewheel', function() {});

Pour le traiter, j'utilise:

function (event) {
    var direction = null,
        key;

    if (event.type === 'mousewheel') {
        if (yourFunctionForGetMouseWheelDirection(event) > 0) {
            direction = 'up';
        } else {
            direction = 'down';
        }
    }
}
Szymon Toda
la source
Vous n'avez pas dit ce qui a newUtilities.getMouseWheelDirection
ccsakuweb
C'est hors de portée de cette question. Donc ce n'est pas un site Web de copier-coller.
Szymon Toda