web-dev-qa-db-fra.com

Comment détecter la direction de défilement

Je souhaite exécuter une fonction lorsque quelqu'un fait défiler un élément vers le bas. Quelque chose comme ça:

 $('div').scrollDown(function(){ alert('down') });
 $('div').scrollUp(function(){ alert('up') });

Mais ces fonctions n'existent pas. Y at-il une solution à ce problème? Ils semblent être capables de le faire. Malheureusement, le code source est compressé, donc pas de chance là-bas ...

Merci!!

57
Rik de Vos

J'ai réussi à comprendre à la fin, donc si quelqu'un cherche la réponse:

 //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;
 });
105
Rik de Vos

L'exemple suivant n'écoutera que le défilement MOUSE, pas de défilement tactile ni le pavé tactile.

Il utilise jQuery.on () (À partir de jQuery 1.7, la méthode .on () est la méthode recommandée pour attacher des gestionnaires d'événements à un document).

$('#elem').on( 'DOMMouseScroll mousewheel', function ( event ) {
  if( event.originalEvent.detail > 0 || event.originalEvent.wheelDelta < 0 ) { //alternative options for wheelData: wheelDeltaX & wheelDeltaY
    //scroll down
    console.log('Down');
  } else {
    //scroll up
    console.log('Up');
  }
  //prevent page fom scrolling
  return false;
});

Fonctionne sur tous les navigateurs.

violon: http://jsfiddle.net/honk1/gWnNv/7/

49
honk31

Celui-ci mérite une mise à jour - nous avons maintenant l'événement wheel:

$(function() {

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

        var delta = e.originalEvent.deltaY;

        if (delta > 0) $('body').text('down');
        else $('body').text('up');

        return false; // this line is only added so the whole page won't scroll in the demo
});
});
body {
  font-size: 22px;
  text-align: center;
  color: white;
  background: grey;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Le support est déjà assez bon sur les navigateurs modernes:

  • Chrome 31+
  • Firefox 17+
  • IE9 +
  • Opéra 18+
  • Safari 7+

https://developer.mozilla.org/en-US/docs/Web/Events/wheel

Si un support plus important du navigateur est requis, il est probablement préférable d’utiliser mousewheel.js au lieu de déconner:

https://plugins.jquery.com/mousewheel/

$(function() {

$(window).mousewheel(function(turn, delta) {

        if (delta > 0) $('body').text('up');
        else $('body').text('down');

        return false; // this line is only added so the whole page won't scroll in the demo
});
});
body {
  font-size: 22px;
  text-align: center;
  color: white;
  background: grey;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.1.13/jquery.mousewheel.min.js"></script>
40
Shikkediel

Solution existante

Il pourrait y avoir 3 solution à partir de cette publication et autre article de stackoverflow .

Solution 1

    var lastScrollTop = 0;
    $(window).on('scroll', function() {
        st = $(this).scrollTop();
        if(st < lastScrollTop) {
            console.log('up 1');
        }
        else {
            console.log('down 1');
        }
        lastScrollTop = st;
    });

Solution 2

    $('body').on('DOMMouseScroll', function(e){
        if(e.originalEvent.detail < 0) {
            console.log('up 2');
        }
        else {
            console.log('down 2');
        }
    });

Solution 3

    $('body').on('mousewheel', function(e){
        if(e.originalEvent.wheelDelta > 0) {
            console.log('up 3');
        }
        else {
            console.log('down 3');
        }
    });

Test multi-navigateur

Je ne pouvais pas le tester sur Safari

chrome 42 (Win 7)

  • Solution 1
    • Up: 1 événement pour 1 défilement
    • Down: 1 événement pour 1 défilement
  • Soltion 2
    • Up: ne fonctionne pas
    • Down: ne fonctionne pas
  • Solution 3
    • Up: 1 événement pour 1 défilement
    • Down: 1 événement pour 1 défilement

Firefox 37 (Win 7)

  • Solution 1
    • Up: 20 événements pour 1 rouleau
    • Down: 20 événements pour 1 parchemin
  • Soltion 2
    • Up: ne fonctionne pas
    • Down: 1 événement pour 1 défilement
  • Solution 3
    • Up: ne fonctionne pas
    • Down: ne fonctionne pas

IE 11 (Win 8)

  • Solution 1
    • Vers le haut: 10 événements pour 1 défilement (effet secondaire: le défilement vers le bas est intervenu enfin)
    • Down: 10 événements pour 1 parchemin
  • Soltion 2
    • Up: ne fonctionne pas
    • Down: ne fonctionne pas
  • Solution 3
    • Up: ne fonctionne pas
    • Down: 1 événement pour 1 défilement

IE 10 (Win 7)

  • Solution 1
    • Up: 1 événement pour 1 défilement
    • Down: 1 événement pour 1 défilement
  • Soltion 2
    • Up: ne fonctionne pas
    • Down: ne fonctionne pas
  • Solution 3
    • Up: 1 événement pour 1 défilement
    • Down: 1 événement pour 1 défilement

IE 9 (Win 7)

  • Solution 1
    • Up: 1 événement pour 1 défilement
    • Down: 1 événement pour 1 défilement
  • Soltion 2
    • Up: ne fonctionne pas
    • Down: ne fonctionne pas
  • Solution 3
    • Up: 1 événement pour 1 défilement
    • Down: 1 événement pour 1 défilement

IE 8 (Win 7)

  • Solution 1
    • Vers le haut: 2 événements pour 1 défilement (effet secondaire: le défilement vers le bas est intervenu enfin)
    • Down: 2 ~ 4 événements par 1 défilement
  • Soltion 2
    • Up: ne fonctionne pas
    • Down: ne fonctionne pas
  • Solution 3
    • Up: 1 événement pour 1 défilement
    • Down: 1 événement pour 1 défilement

Solution combinée

J'ai vérifié cet effet secondaire de IE 11 et IE 8 est issu de if else déclaration. Donc, je l'ai remplacé par if else if déclaration comme suit.

Du test multi-navigateur, j'ai décidé d'utiliser Solution 3 pour les navigateurs courants et Solution 1 pour firefox et IE 11.

J'ai fait référence à cette réponse pour détecter IE 11.

    // Detect IE version
    var iev=0;
    var ieold = (/MSIE (\d+\.\d+);/.test(navigator.userAgent));
    var trident = !!navigator.userAgent.match(/Trident\/7.0/);
    var rv=navigator.userAgent.indexOf("rv:11.0");

    if (ieold) iev=new Number(RegExp.$1);
    if (navigator.appVersion.indexOf("MSIE 10") != -1) iev=10;
    if (trident&&rv!=-1) iev=11;

    // Firefox or IE 11
    if(typeof InstallTrigger !== 'undefined' || iev == 11) {
        var lastScrollTop = 0;
        $(window).on('scroll', function() {
            st = $(this).scrollTop();
            if(st < lastScrollTop) {
                console.log('Up');
            }
            else if(st > lastScrollTop) {
                console.log('Down');
            }
            lastScrollTop = st;
        });
    }
    // Other browsers
    else {
        $('body').on('mousewheel', function(e){
            if(e.originalEvent.wheelDelta > 0) {
                console.log('Up');
            }
            else if(e.originalEvent.wheelDelta < 0) {
                console.log('Down');
            }
        });
    }
22
$(function(){
    var _top = $(window).scrollTop();
    var _direction;
    $(window).scroll(function(){
        var _cur_top = $(window).scrollTop();
        if(_top < _cur_top)
        {
            _direction = 'down';
        }
        else
        {
            _direction = 'up';
        }
        _top = _cur_top;
        console.log(_direction);
    });
});

Démo: http://jsfiddle.net/AlienWebguy/Bka6F/

9
AlienWebguy
var mousewheelevt = (/Firefox/i.test(navigator.userAgent)) ? "DOMMouseScroll" : "mousewheel" //FF doesn't recognize mousewheel as of FF3.x
$(document).bind(mousewheelevt, 
function(e)
    {
        var evt = window.event || e //equalize event object     
        evt = evt.originalEvent ? evt.originalEvent : evt; //convert to originalEvent if possible               
        var delta = evt.detail ? evt.detail*(-40) : evt.wheelDelta //check for detail first, because it is used by Opera and FF
        if(delta > 0) 
            {
            scrollup();
            }
        else
            {
            scrolldown();
            }   
    }
);
0
Jithin U. Ahmed

Vous pouvez utiliser ce simple plugin pour ajouter scrollUp et scrollDown à votre jQuery

https://github.com/phpust/JQueryScrollDetector

var lastScrollTop = 0;
var action = "stopped";
var timeout = 100;
// Scroll end detector:
$.fn.scrollEnd = function(callback, timeout) {    
      $(this).scroll(function(){
        // get current scroll top 
        var st = $(this).scrollTop();
        var $this = $(this);
        // fix for page loads
        if (lastScrollTop !=0 )
        {
            // if it's scroll up
            if (st < lastScrollTop){
                action = "scrollUp";
            } 
            // else if it's scroll down
            else if (st > lastScrollTop){
                action = "scrollDown";
            }
        }
        // set the current scroll as last scroll top
        lastScrollTop = st;
        // check if scrollTimeout is set then clear it
        if ($this.data('scrollTimeout')) {
          clearTimeout($this.data('scrollTimeout'));
        }
        // wait until timeout done to overwrite scrolls output
        $this.data('scrollTimeout', setTimeout(callback,timeout));
    });
};

$(window).scrollEnd(function(){
    if(action!="stopped"){
        //call the event listener attached to obj.
        $(document).trigger(action); 
    }
}, timeout);
0
user122293

Voici un exemple montrant un moyen facile de le faire. Le script est:

$(function() {
  var _t = $("#container").scrollTop();
  $("#container").scroll(function() {
    var _n = $("#container").scrollTop();
    if (_n > _t) {
      $("#target").text("Down");
    } else {
      $("#target").text("Up");
    }
    _t = _n;
  });
});

Le #container est votre div id. Le #target est juste pour le voir fonctionner. Changez pour ce que vous voulez quand vous êtes en haut ou en bas.

[~ # ~] éditer [~ # ~]

L'OP n'a pas dit avant, mais depuis qu'il utilise une div avec overflow: hidden, le défilement ne se produit pas, le script pour détecter le défilement est le moindre. Eh bien, comment détecter quelque chose qui ne se produit pas?!

Donc, l’opérateur lui-même a posté le lien avec ce qu’il veut, alors pourquoi ne pas utiliser cette bibliothèque? http://cdn.jquerytools.org/1.2.5/full/jquery.tools.min.js .

L'appel est juste:

$(function() {
    $(".scrollable").scrollable({ vertical: true, mousewheel: true });
});
0
Erick Petrucelli