jQuery scroll () erkennt, wenn der Benutzer den Bildlauf beendet


109

Ok damit ..

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

Ich kann anhand meines Verständnisses erkennen, wann jemand einen Bildlauf durchführt. Damit versuche ich herauszufinden, wie man fängt, wenn jemand angehalten hat. Aus dem obigen Beispiel können Sie ersehen, dass ich eine Klasse aus einer Reihe von Elementen entferne, während das Scrollen stattfindet. Ich möchte diese Klasse jedoch wieder aktivieren, wenn der Benutzer aufhört zu scrollen.

Der Grund dafür ist, dass ich beabsichtige, eine Zwischenstopp-Show zu haben, während die Seite gescrollt wird, um der Seite einen besonderen Effekt zu verleihen, an dem ich arbeiten möchte. Aber die eine Klasse, die ich beim Scrollen entfernen möchte, widerspricht diesem Effekt, da er für manche Natur ein Transparenzeffekt ist.



Genial, nicht genau doppelt, aber definitiv die Gasse hoch, nach der ich gesucht habe, und hat mir am Ende geholfen, mein Problem zu lösen. Danke dir.
Chris

Antworten:


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

Aktualisieren

Ich habe eine Erweiterung geschrieben , um den Standard- onEvent-Handler von jQuery zu verbessern . Es fügt den ausgewählten Elementen eine Ereignishandlerfunktion für ein oder mehrere Ereignisse hinzu und ruft die Handlerfunktion auf, wenn das Ereignis für ein bestimmtes Intervall nicht ausgelöst wurde. Dies ist nützlich, wenn Sie einen Rückruf erst nach einer Verzögerung wie dem Größenänderungsereignis oder dergleichen auslösen möchten.

Es ist wichtig, das Github-Repo auf Updates zu überprüfen!

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

Verwenden Sie es wie jeden anderen onoder bind-event-Handler, außer dass Sie als letzten einen zusätzlichen Parameter übergeben können:

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

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

(Diese Demo verwendet resizestattdessen scroll, aber wen interessiert das?!)


Es ist immer noch nicht 100% genau: Manchmal stoppt der Benutzer das Scrollen und setzt es auch nach 250 ms fort
Arman Bimatov,

Dieser Code funktioniert hervorragend, hat aber das Autocomplete-Widget von jquery ui völlig zerstört.
kkazakov

@ArmanBimatov dann wird es berücksichtigt, wenn der Benutzer weiter scrollt, was gut klingt, nein?
Godblessstrawberry

Dieses Zeitlimit wird nur ausgelöst, wenn Bildlaufereignisse gestoppt werden und NICHT, wenn der Benutzer das Bildlauf beendet. Der Benutzer kann seinen Finger von der Maus heben und das Scrollen kann abhängig von der Geschwindigkeit des Scrollens einige Sekunden lang fortgesetzt werden. Diese Lösung gibt Ihnen keinen Hinweis darauf, wann der Benutzer das Scrollen beendet hat.
AndroidDev

1
@abzarak dieser abstrakte Helfer ist auf keinen Fall perfekt! Ich habe das Github-Repo aus bestimmten Gründen in letzter Zeit nicht aktualisiert - das war eine schreckliche Idee. Verwenden Sie stattdessen einfach eine Wrapper-Funktion "Gas" oder "Entprellen". Ich sollte das auch woanders beachten! :)
Yckart

49

Verwenden von jQuery Gas / Entprellen

jQuery Debounce ist eine gute Lösung für solche Probleme. jsFidlle

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

Der zweite Parameter ist das Flag "at_begin". Hier habe ich gezeigt, wie Code sowohl bei "Bildlaufstart" als auch bei "Bildlaufende" ausgeführt wird.

Verwenden von Lodash

Wie von Barry P vorgeschlagen, haben jsFiddle , Unterstrich oder lodash auch einen Debounce, jeder mit leicht unterschiedlichen Apis.

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

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

Ist es möglich, gleichzeitig eine normale Bildlauffunktion zu verwenden? $ (Fenster) .scroll (Funktion () {...});
Daniel Vogelnest

Natürlich bindet jQuery so viele Handler an ein Ereignis, wie Sie möchten.
Sinetheta

Vielen Dank für die Aktualisierung dieses @BarryP Jsfiddle bietet auch Lo-Dash, so dass Sie den externen Link jsfiddle.net/qjggnyhf
Sinetheta

Zu Ihrer Information, ich hatte Probleme, bei denen schnelle Schriftrollen nicht zurückgingen. Es schien, als müssten Sie der "STOPPED" -Entprellung einige Millisekunden hinzufügen, da dies sonst zu einer Rennbedingung führt, bei der STOPPED irgendwann vor dem STARTED ausgelöst wird und das Element stecken bleibt, als ob Sie noch scrollen. Ich habe meine 150 und 160 gemacht, und es schien den Trick zu tun.
CodeChimp

Danke @CodeChimp, das ist ordentlich, aber ich hatte mir Sorgen um die Behandlung von Randfällen gemacht, indem ich sie 15 von 16 Mal repariert habe;) Vielleicht wäre ein einzelner Handler mit der gesamten Logik am sichersten. Überprüfen Sie das leadingund sich trailingselbst, dann stellen Sie sicher, dass es keine Verwirrung geben kann.
Sinetheta

9

Rob W schlug vor, dass ich mir hier auf dem Stapel einen anderen Beitrag anschaue, der im Wesentlichen meinem ursprünglichen Beitrag ähnlich war. Beim Lesen habe ich einen Link zu einer Seite gefunden:

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

Dies hat mir letztendlich geholfen, mein Problem sehr gut zu lösen, nachdem ich ein wenig an meine eigenen Bedürfnisse angepasst hatte, aber insgesamt hat es mir geholfen, viel Ärger aus dem Weg zu räumen und mir ungefähr 4 Stunden Zeit zu sparen, es selbst herauszufinden.

Da dieser Beitrag einen gewissen Wert zu haben scheint, dachte ich, ich würde zurückkommen und den Code bereitstellen, der ursprünglich auf dem genannten Link gefunden wurde, für den Fall, dass der Autor jemals beschließt, mit der Site eine andere Richtung einzuschlagen, und den Link schließlich entfernt.

(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

Ich stimmte einigen der obigen Kommentare zu, dass das Abhören einer Zeitüberschreitung nicht genau genug war, da dies ausgelöst wird, wenn Sie die Bildlaufleiste nicht mehr lange genug bewegen, anstatt wenn Sie aufhören zu scrollen. Ich denke, eine bessere Lösung besteht darin, darauf zu achten, dass der Benutzer die Maus loslässt (mouseup), sobald er mit dem Scrollen beginnt:

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

Ein Beispiel dafür ist in dieser JSFiddle zu sehen


2
Dies scheint großartig zu sein, aber wenn Sie mit einer 2-Finger-Geste auf einem Trackpad oder einem Scrollrad scrollen, wird das Mouseup nicht ausgelöst. Dies ist wahrscheinlich auch die häufigste Art zu scrollen, was es problematisch macht.
Adam

1
Guter Punkt. Aber möglicherweise gibt es ein paar Korrekturen dafür. Verwenden Sie das "Mausrad" -Ereignis von jquery oder verfolgen Sie, ob die Maus zuerst heruntergefahren wurde, und verwenden Sie einen von anderen vorgeschlagenen Timeout-Ansatz. Aber ich denke, die Verwendung einer Kombination aus anderen Antworten für Mausradereignisse und dieser Antwort für das Ziehen der Bildlaufleiste liefert die genauesten Ergebnisse
Theo

3

Sie können ein Intervall festlegen, das etwa alle 500 ms ausgeführt wird.

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

Ich habe diesen Code nicht getestet, aber das Prinzip sollte funktionieren.


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

sehr kleine Version mit Start- und Endfähigkeit


1

Ok, das habe ich schon mal benutzt. Grundsätzlich sehen Sie einen Hold a Ref bis zum letzten scrollTop(). Sobald Ihre Zeitüberschreitung verstrichen ist, überprüfen Sie die aktuelle scrollTop()und wenn sie gleich sind, können Sie mit dem Scrollen fertig sein.

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

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

  currentScrollTop = $(this).scrollTop()
)

1

ES6-Stil mit Überprüfung des Bildlaufstarts ebenfalls.

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

Verwendung:

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

Für diejenigen, die dies noch brauchen, ist hier die Lösung

  $(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

Das sollte funktionieren:

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

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

0

So können Sie damit umgehen:

    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

Dies erkennt den Bildlaufstopp nach 1 Millisekunde (oder ändert ihn) mithilfe eines globalen Timers:

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.
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.