web-dev-qa-db-fra.com

Evénement lorsque l'utilisateur cesse de faire défiler

Je voudrais faire quelques trucs jQuery fantaisie lorsque l'utilisateur fait défiler la page. Mais je ne sais pas comment aborder ce problème, car il n'y a que la méthode scroll ().

Des idées?

48
dantz

Vous pouvez attribuer à la scroll() un délai qui est écrasé à chaque défilement de l'utilisateur. De cette façon, lorsqu'il s’arrête après un certain nombre de millisecondes, votre script est exécuté, mais s’il défile entre-temps, le compteur recommencera et le script attendra jusqu’à ce que le défilement soit terminé.

Mettre à jour:

Parce que cette question a encore une fois de l'action, j'ai pensé que je pourrais aussi bien la mettre à jour avec une extension jQuery qui ajoute un événement scrollEnd

// extension:
$.fn.scrollEnd = function(callback, timeout) {          
  $(this).scroll(function(){
    var $this = $(this);
    if ($this.data('scrollTimeout')) {
      clearTimeout($this.data('scrollTimeout'));
    }
    $this.data('scrollTimeout', setTimeout(callback,timeout));
  });
};

// how to call it (with a 1000ms timeout):
$(window).scrollEnd(function(){
    alert('stopped scrolling');
}, 1000);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div style="height: 200vh">
  Long div
</div>

66
Stephan Muller

Voici un exemple simple d'utilisation de setTimeout pour lancer une fonction lorsque l'utilisateur cesse de faire défiler:

(function() {        
    var timer;
    $(window).bind('scroll',function () {
        clearTimeout(timer);
        timer = setTimeout( refresh , 150 );
    });
    var refresh = function () { 
        // do stuff
        console.log('Stopped Scrolling'); 
    };
})();

La minuterie est effacée pendant le déroulement de l'événement de défilement. Une fois le défilement terminé, la fonction d'actualisation est activée.

Ou sous forme de plugin: 

$.fn.afterwards = function (event, callback, timeout) {
    var self = $(this), delay = timeout || 16;

    self.each(function () { 
        var $t = $(this);
        $t.on(event, function(){
            if ($t.data(event+'-timeout')) {
                clearTimeout($t.data(event+'-timeout'));
            }
            $t.data(event + '-timeout', setTimeout(function () { callback.apply($t); },delay));
        })
    });
    return this;
};

Pour déclencher un rappel après 100 ms du dernier événement de défilement sur un div (avec un espace de nom):

$('div.mydiv').afterwards('scroll.mynamespace', function(e) {
        // do stuff when stops scrolling
        $(this).addClass('stopped');
    }, 100
);

J'utilise cela pour faire défiler et redimensionner. 

58
Phil M

Voici une autre solution plus générique basée sur les mêmes idées mentionnées:

var delayedExec = function(after, fn) {
    var timer;
    return function() {
        timer && clearTimeout(timer);
        timer = setTimeout(fn, after);
    };
};

var scrollStopper = delayedExec(500, function() {
    console.log('stopped it');
});

document.getElementById('box').addEventListener('scroll', scrollStopper);
9
xat

Pourquoi si compliqué? Comme le souligne la documentation, cette http://jsfiddle.net/x3s7F/9/ fonctionne!

$('.frame').scroll(function() {
 $('.back').hide().fadeIn(100);
}

_ { http://api.jquery.com/scroll/ .


Remarque: L'événement scroll sous Windows Chrome est différent de tous les autres. Vous devez faire défiler rapidement pour obtenir le même résultat que dans l'exemple. FF. Regardez https://liebdich.biz/back.min.js la fonction "X".

Quelques résultats de mon test how many ms a scroll event:

  • Safari, Mac FF, Mac Chrome: ~ 16 ms par événement.
  • Windows FF: ~ 19 ms par événement.
  • Windows Chrome: jusqu'à environ 130 ms par événement, lors d'un défilement lent.
  • Internet Explorer: jusqu'à environ 110 ms par événement.

http://jsfiddle.net/TRNCFRMCN/1Lygop32/4/ .

2
loveNoHate

J'ai eu le besoin de mettre en œuvre onScrollEnd événement discuté aussi bien entendre .

J'implémente ceci en utilisant JavaScript Module Pattern :

var WindowCustomEventsModule = (function(){

    var _scrollEndTimeout = 30;

    var _delayedExec = function(callback){
        var timer;
        return function(){
            timer && clearTimeout(timer);
            timer = setTimeout(callback, _scrollEndTimeout);
        }
    };

    var onScrollEnd = function(callback) { 
        window.addEventListener('scroll', _delayedExec(callback), false);         
    };

    return {
        onScrollEnd: onScrollEnd
    }
})();

// usage example
WindowCustomEventsModule.onScrollEnd(function(){
    //
    // do stuff
    //
});

J'espère que cela aidera/inspirera quelqu'un

1
Martin Kuzdowicz

Il existe des fonctions scrollstart et scrollstop faisant partie de jquery mobile. 

Exemple d'utilisation de scrollstop:

$(document).on("scrollstop",function(){
   alert("Stopped scrolling!");
});

J'espère que ça aide quelqu'un.

1
Dima

Il n'y a pas d'événement tel que 'scrollEnd'. Je vous recommande de vérifier la valeur renvoyée par scroll() de temps en temps (par exemple, 200 ms) à l'aide de setInterval et d'enregistrer le delta entre la valeur actuelle et la valeur précédente. Si le delta devient nul, vous pouvez l'utiliser comme événement.

0
dpq

J'ai extrait du code d'un élément rapide que j'ai bricolé pour le faire à titre d'exemple (notez que scroll.chain est un objet contenant deux tableaux début et fin contenant des conteneurs pour les fonctions de rappel). Notez également que j'utilise jQuery et soulignez ici.

$('body').on('scroll', scrollCall);
scrollBind('end', callbackFunction);
scrollBind('start', callbackFunction);

var scrollCall = function(e) {
    if (scroll.last === false || (Date.now() - scroll.last) <= 500) {
        scroll.last = Date.now();
        if (scroll.timeout !== false) {
            window.clearTimeout(scroll.timeout);
        } else {
            _(scroll.chain.start).each(function(f){
                f.call(window, {type: 'start'}, e.event);
            });
        }
        scroll.timeout = window.setTimeout(self.scrollCall, 550, {callback: true, event: e});
        return;
    }
    if (e.callback !== undefined) {
        _(scroll.chain.end).each(function(f){
            f.call(window, {type: 'end'}, e.event);
        });
        scroll.last = false;
        scroll.timeout = false;
    }
};

var scrollBind = function(type, func) {
    type = type.toLowerCase();
    if (_(scroll.chain).has(type)) {
        if (_(scroll.chain[type]).indexOf(func) === -1) {
            scroll.chain[type].Push(func);
            return true;
        }
        return false;
    }
    return false;
}
0
whoughton