jQuery scroll () rileva quando l'utente smette di scorrere


109

Ok con questo ..

$(window).scroll(function()
{
    $('.slides_layover').removeClass('showing_layover');
    $('#slides_effect').show();
});

Posso dire quando qualcuno sta scorrendo da quello che ho capito. Quindi con questo sto cercando di capire come catturare quando qualcuno si è fermato. Dall'esempio sopra puoi vedere che sto rimuovendo una classe da un insieme di elementi mentre è in corso lo scorrimento. Tuttavia, voglio riattivare quella classe quando l'utente smette di scorrere.

La ragione di ciò è che intendo fare uno spettacolo di sosta mentre la pagina scorre per dare alla pagina un effetto speciale su cui sto tentando di lavorare. Ma l'unica classe che sto cercando di rimuovere durante lo scorrimento è in conflitto con quell'effetto poiché è un effetto di trasparenza per qualche natura.



Fantastico, non esattamente duplicato ma decisamente all'altezza di ciò che stavo cercando e mi ha aiutato a risolvere il mio problema. Grazie.
chris

Risposte:


253
$(window).scroll(function() {
    clearTimeout($.data(this, 'scrollTimer'));
    $.data(this, 'scrollTimer', setTimeout(function() {
        // do something
        console.log("Haven't scrolled in 250ms!");
    }, 250));
});

Aggiornare

Ho scritto un'estensione per migliorare il ongestore eventi predefinito di jQuery . Allega una funzione di gestore di eventi per uno o più eventi agli elementi selezionati e chiama la funzione di gestore se l'evento non è stato attivato per un determinato intervallo. Ciò è utile se desideri attivare una richiamata solo dopo un ritardo, come l'evento di ridimensionamento o simili.

È importante controllare il github-repo per gli aggiornamenti!

https://github.com/yckart/jquery.unevent.js

;(function ($) {
    var on = $.fn.on, timer;
    $.fn.on = function () {
        var args = Array.apply(null, arguments);
        var last = args[args.length - 1];

        if (isNaN(last) || (last === 1 && args.pop())) return on.apply(this, args);

        var delay = args.pop();
        var fn = args.pop();

        args.push(function () {
            var self = this, params = arguments;
            clearTimeout(timer);
            timer = setTimeout(function () {
                fn.apply(self, params);
            }, delay);
        });

        return on.apply(this, args);
    };
}(this.jQuery || this.Zepto));

Usalo come qualsiasi altro ono bind-Event gestore, salvo che è possibile passare un parametro aggiuntivo come ultimo:

$(window).on('scroll', function(e) {
    console.log(e.type + '-event was 250ms not triggered');
}, 250);

http://yckart.github.com/jquery.unevent.js/

(questa demo usa resizeinvece di scroll, ma chi se ne frega ?!)


Non è ancora preciso al 100%: a volte l'utente interrompe e riprende lo scorrimento anche dopo 250 ms
Arman Bimatov

Questo codice funziona alla grande, ma ha rotto totalmente il widget di completamento automatico di jquery ui.
kkazakov

@ArmanBimatov allora verrà considerato mentre l'utente continua a scorrere, che suona bene, no?
godblessstrawberry

Questo timeout si attiva solo quando gli eventi di scorrimento si interrompono e NON quando l'utente interrompe lo scorrimento. L'utente può sollevare il dito dal mouse e lo scorrimento può continuare per alcuni secondi a seconda della velocità di scorrimento. Questa soluzione non ti darà un'indicazione quando l'utente ha smesso di scorrere.
AndroidDev

1
@abzarak questo aiutante astratto non è perfetto, in nessun caso! Non ho aggiornato il repository github di recente, per ragioni: questa è stata un'idea terribile. Utilizza invece una funzione wrapper "throttle" o "debounce". Dovrei notare che anche da qualche altra parte! :)
yckart

49

Utilizzando jQuery throttle / debounce

jQuery debounce è utile per problemi come questo. jsFidlle

$(window).scroll($.debounce( 250, true, function(){
    $('#scrollMsg').html('SCROLLING!');
}));
$(window).scroll($.debounce( 250, function(){
    $('#scrollMsg').html('DONE!');
}));

Il secondo parametro è il flag "at_begin". Qui ho mostrato come eseguire il codice sia a "inizio scorrimento" che a "fine scorrimento".

Usare Lodash

Come suggerito da Barry P, jsFiddle , underscore o lodash hanno anche un debounce, ciascuno con api leggermente diverse.

$(window).scroll(_.debounce(function(){
    $('#scrollMsg').html('SCROLLING!');
}, 150, { 'leading': true, 'trailing': false }));

$(window).scroll(_.debounce(function(){
    $('#scrollMsg').html('STOPPED!');
}, 150));

È possibile utilizzare contemporaneamente una normale funzione di scorrimento? $ (finestra) .scroll (function () {...});
Daniel Vogelnest

Ovviamente, jQuery vincolerà tutti i gestori che desideri a un evento.
Sinetheta

Grazie per aver aggiornato questo @BarryP Jsfiddle fornisce anche lo-dash in modo da poter evitare il collegamento esterno jsfiddle.net/qjggnyhf
Sinetheta

Cordiali saluti, stavo avendo problemi per i quali i pergamene veloci non venivano ripristinati. Sembrava che fosse necessario aggiungere qualche millisecondo al debounce "STOPPED", altrimenti causa una condizione di competizione in cui, a volte, STOPPED si innesca prima di STARTED, e si finisce con l'elemento bloccato come se si stesse ancora scorrendo. Ho fatto il mio 150 e 160, rispettivamente, e sembrava fare il trucco.
CodeChimp

Grazie @CodeChimp è pulito, ma mi preoccupavo di gestire casi limite risolvendoli 15 volte su 16;) Forse un singolo gestore con tutta la logica all'interno sarebbe stato il più sicuro. Controlla tu stesso leadinge trailing, quindi assicurati che non ci possa essere confusione.
Sinetheta

9

Rob W ha suggerito di dare un'occhiata a un altro post qui in pila che era essenzialmente un post simile al mio originale. Quale leggendo questo ho trovato un collegamento a un sito:

http://james.padolsey.com/javascript/special-scroll-events-for-jquery/

Questo in realtà ha finito per aiutare a risolvere il mio problema molto bene dopo un piccolo ritocco per le mie esigenze, ma tutto sommato mi ha aiutato a togliermi di mezzo un sacco di guff e mi ha risparmiato circa 4 ore per risolverlo da solo.

Visto che questo post sembra avere qualche merito, ho pensato che sarei tornato e avrei fornito il codice trovato originariamente sul link menzionato, nel caso in cui l'autore avesse deciso di andare in una direzione diversa con il sito e avesse finito per rimuovere il collegamento.

(function(){

    var special = jQuery.event.special,
        uid1 = 'D' + (+new Date()),
        uid2 = 'D' + (+new Date() + 1);

    special.scrollstart = {
        setup: function() {

            var timer,
                handler =  function(evt) {

                    var _self = this,
                        _args = arguments;

                    if (timer) {
                        clearTimeout(timer);
                    } else {
                        evt.type = 'scrollstart';
                        jQuery.event.handle.apply(_self, _args);
                    }

                    timer = setTimeout( function(){
                        timer = null;
                    }, special.scrollstop.latency);

                };

            jQuery(this).bind('scroll', handler).data(uid1, handler);

        },
        teardown: function(){
            jQuery(this).unbind( 'scroll', jQuery(this).data(uid1) );
        }
    };

    special.scrollstop = {
        latency: 300,
        setup: function() {

            var timer,
                    handler = function(evt) {

                    var _self = this,
                        _args = arguments;

                    if (timer) {
                        clearTimeout(timer);
                    }

                    timer = setTimeout( function(){

                        timer = null;
                        evt.type = 'scrollstop';
                        jQuery.event.handle.apply(_self, _args);

                    }, special.scrollstop.latency);

                };

            jQuery(this).bind('scroll', handler).data(uid2, handler);

        },
        teardown: function() {
            jQuery(this).unbind( 'scroll', jQuery(this).data(uid2) );
        }
    };

})();

5

Sono d'accordo con alcuni dei commenti sopra che l'ascolto di un timeout non era abbastanza accurato in quanto si attiverà quando smetti di spostare la barra di scorrimento per un tempo sufficientemente lungo invece di quando smetti di scorrere. Penso che una soluzione migliore sia ascoltare l'utente che lascia andare il mouse (mouseup) non appena inizia a scorrere:

$(window).scroll(function(){
    $('#scrollMsg').html('SCROLLING!');
    var stopListener = $(window).mouseup(function(){ // listen to mouse up
        $('#scrollMsg').html('STOPPED SCROLLING!');
        stopListner(); // Stop listening to mouse up after heard for the first time 
    });
});

e un esempio del suo funzionamento può essere visto in questo JSFiddle


2
Sembra fantastico, ma se stai scorrendo con il gesto a due dita su un trackpad o una rotella di scorrimento, il mouse non viene attivato. Questo è probabilmente anche il modo più comune per scorrere, il che lo rende problematico.
Adam

1
Buon punto. Ma potenzialmente ci sono un paio di soluzioni per questo. Utilizzando l'evento "mousewheel" di jquery o tenendo traccia di se mousedown prima, e utilizzando un approccio di timeout come suggerito da altri. Ma penso che l'uso di una combinazione di altre risposte per gli eventi della rotellina del mouse e questa risposta per il trascinamento della barra di scorrimento darà i risultati più accurati
Theo

3

È possibile impostare un intervallo che viene eseguito ogni 500 ms circa, sulla falsariga di quanto segue:

var curOffset, oldOffset;
oldOffset = $(window).scrollTop();
var $el = $('.slides_layover'); // cache jquery ref
setInterval(function() {
  curOffset = $(window).scrollTop();
  if(curOffset != oldOffset) {
    // they're scrolling, remove your class here if it exists
    if($el.hasClass('showing_layover')) $el.removeClass('showing_layover');
  } else {
    // they've stopped, add the class if it doesn't exist
    if(!$el.hasClass('showing_layover')) $el.addClass('showing_layover');
  }
  oldOffset = curOffset;
}, 500);

Non ho testato questo codice, ma il principio dovrebbe funzionare.


2
function scrolled() {
    //do by scroll start
    $(this).off('scroll')[0].setTimeout(function(){
        //do by scroll end
        $(this).on('scroll',scrolled);
    }, 500)
}
$(window).on('scroll',scrolled);

Versione molto piccola con capacità di inizio e fine


1

Ok, questo è qualcosa che ho usato prima. Fondamentalmente sembri una stretta fino all'ultimo scrollTop(). Una volta che il timeout è scaduto, controlli la corrente scrollTop()e se sono uguali, hai finito di scorrere.

$(window).scroll((e) ->
  clearTimeout(scrollTimer)
  $('header').addClass('hidden')

  scrollTimer = setTimeout((() ->
    if $(this).scrollTop() is currentScrollTop
      $('header').removeClass('hidden') 
  ), animationDuration)

  currentScrollTop = $(this).scrollTop()
)

1

Stile ES6 con controllo anche dell'avvio dello scorrimento.

function onScrollHandler(params: {
  onStart: () => void,
  onStop: () => void,
  timeout: number
}) {
  const {onStart, onStop, timeout = 200} = params
  let timer = null

  return (event) => {
    if (timer) {
      clearTimeout(timer)
    } else {
      onStart && onStart(event)
    }
    timer = setTimeout(() => {
      timer = null
      onStop && onStop(event)
    }, timeout)
  }
}

Uso:

yourScrollableElement.addEventListener('scroll', onScrollHandler({
  onStart: (event) => {
    console.log('Scrolling has started')
  },
  onStop: (event) => {
    console.log('Scrolling has stopped')
  },
  timeout: 123 // Remove to use default value
}))


0

Per coloro che hanno ancora bisogno di questo, ecco la soluzione

  $(function(){
      var t;
      document.addEventListener('scroll',function(e){
          clearTimeout(t);
          checkScroll();
      });
      
      function checkScroll(){
          t = setTimeout(function(){
             alert('Done Scrolling');
          },500); /* You can increase or reduse timer */
      }
  });


0

Questo dovrebbe funzionare:

var Timer;
$('.Scroll_Table_Div').on("scroll",function() 
{
    // do somethings

    clearTimeout(Timer);
    Timer = setTimeout(function()
    {
        console.log('scrolling is stop');
    },50);
});

0

Ecco come puoi gestirlo:

    var scrollStop = function (callback) {
        if (!callback || typeof callback !== 'function') return;
        var isScrolling;
        window.addEventListener('scroll', function (event) {
            window.clearTimeout(isScrolling);
            isScrolling = setTimeout(function() {
                callback();
            }, 66);
        }, false);
    };
    scrollStop(function () {
        console.log('Scrolling has stopped.');
    });
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>.<br>
</body>
</html>


0

Questo rileva l'arresto dello scorrimento dopo 1 millisecondo (o lo modifica) utilizzando un timer globale:

var scrollTimer;

$(window).on("scroll",function(){
    clearTimeout(scrollTimer);
    //Do  what you want whilst scrolling
    scrollTimer=setTimeout(function(){afterScroll()},1);
})

function afterScroll(){
    //I catched scroll stop.
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.