Como detectar a direção de rolagem

Eu quero executar uma function quando alguém rola para baixo em um elemento. Algo assim:

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

Mas essas funções não existem. Existe uma solução para este problema? Eles parecem ser capazes de fazer isso. Infelizmente o código fonte está comprimido, então não tem sorte …

Obrigado!!

Eu consegui descobrir isso no final, então se alguém está procurando a resposta:

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

O exemplo a seguir escutará apenas a rolagem do MOUSE, nenhum toque ou rolagem do trackpad.

Ele usa jQuery.on () (A partir do jQuery 1.7, o método .on () é o método preferido para append manipuladores de events a um documento).

 $('#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; }); 

Funciona em todos os navegadores.

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

Este merece uma atualização – hoje em dia temos o evento 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; } 
  

Solução Existente

Pode haver 3 soluções deste artigo de postagem e outro artigo sobre stackoverflow .

Solução 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; }); 

Solução 2

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

Solução 3

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

Teste de múltiplos navegadores

Eu não pude testar no Safari

chrome 42 (Win 7)

  • Solução 1
    • Up: 1 evento por 1 pergaminho
    • Abaixo: 1 evento por 1 rolagem
  • Soltion 2
    • Up: não funciona
    • Down: não funciona
  • Solução 3
    • Up: 1 evento por 1 pergaminho
    • Abaixo: 1 evento por 1 rolagem

Firefox 37 (Win 7)

  • Solução 1
    • Up: 20 events por 1 pergaminho
    • Abaixo: 20 events por 1 pergaminho
  • Soltion 2
    • Up: não funciona
    • Abaixo: 1 evento por 1 rolagem
  • Solução 3
    • Up: não funciona
    • Down: não funciona

IE 11 (Win 8)

  • Solução 1
    • Para cima: 10 events por 1 rolagem (efeito colateral: rolagem para baixo ocorreu por último)
    • Abaixo: 10 events por 1 rolagem
  • Soltion 2
    • Up: não funciona
    • Down: não funciona
  • Solução 3
    • Up: não funciona
    • Abaixo: 1 evento por 1 rolagem

IE 10 (Win 7)

  • Solução 1
    • Up: 1 evento por 1 pergaminho
    • Abaixo: 1 evento por 1 rolagem
  • Soltion 2
    • Up: não funciona
    • Down: não funciona
  • Solução 3
    • Up: 1 evento por 1 pergaminho
    • Abaixo: 1 evento por 1 rolagem

IE 9 (Win 7)

  • Solução 1
    • Up: 1 evento por 1 pergaminho
    • Abaixo: 1 evento por 1 rolagem
  • Soltion 2
    • Up: não funciona
    • Down: não funciona
  • Solução 3
    • Up: 1 evento por 1 pergaminho
    • Abaixo: 1 evento por 1 rolagem

IE 8 (Win 7)

  • Solução 1
    • Up: 2 ​​events por 1 rolagem (efeito colateral: rolagem para baixo ocorreu por último)
    • Abaixo: 2 a 4 events por 1 rolagem
  • Soltion 2
    • Up: não funciona
    • Down: não funciona
  • Solução 3
    • Up: 1 evento por 1 pergaminho
    • Abaixo: 1 evento por 1 rolagem

Solução combinada

Eu verifiquei que o efeito colateral do IE 11 e IE 8 é proveniente da declaração if else . Então, eu substituí-lo com if else if statement como a seguir.

A partir do teste com vários navegadores, decidi usar a Solução 3 para navegadores comuns e a Solução 1 para o firefox e o IE 11.

Eu referi esta resposta para detectar o 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'); } }); } 
 $(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); }); }); 

Demonstração: http://jsfiddle.net/AlienWebguy/Bka6F/

Aqui está uma amostra mostrando uma maneira fácil de fazer isso. O script é:

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

O #container é seu div id . O #target é apenas para vê-lo funcionando. Mude para o que você quer quando estiver em pé ou quando estiver em baixo.

EDITAR

O OP não disse antes, mas como ele está usando um div com overflow: hidden , a rolagem não ocorre, então o script para detectar o scroll é o menor dele. Bem, como detectar algo que não acontece ?!

Então, o próprio OP postou o link com o que ele quer, então porque não usar essa biblioteca? http://cdn.jquerytools.org/1.2.5/full/jquery.tools.min.js .

A binding é justa:

 $(function() { $(".scrollable").scrollable({ vertical: true, mousewheel: true }); }); 
 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(); } } ); 

Você pode usar este plugin simples para adicionar scrollUp e scrollDown ao seu 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);