jQuery scroll (), kullanıcı kaydırmayı durdurduğunda algılar


109

Tamam bununla ..

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

Birisinin anladığım kadar kaydırdığını söyleyebilirim. Böylece, birisi durduğunda nasıl yakalayacağımı anlamaya çalışıyorum. Yukarıdaki örnekten, kaydırma işlemi devam ederken bir sınıfı bir öğe kümesinden kaldırdığımı görebilirsiniz. Ancak, kullanıcı kaydırmayı bıraktığında bu sınıfı tekrar açmak istiyorum.

Bunun nedeni, sayfaya üzerinde çalıştığım özel bir efekt vermek için sayfa kaydırılırken bir konaklama şovu yapmak niyetindeyim. Ancak kaydırırken kaldırmaya çalıştığım tek sınıf, bazı doğaya saydamlık etkisi olarak bu etkiyle çatışıyor.



Müthiş, tam olarak yinelenen değil, aradığım şeyin kesinlikle sokağında kaldı ve sonunda sorunumu çözmeme yardımcı oldu. Teşekkür ederim.
chris

Yanıtlar:


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

Güncelleme

JQuery'nin varsayılan olay işleyicisini geliştirmek için bir uzantı yazdım on. Seçilen öğelere bir veya daha fazla olay için bir olay işleyici işlevi ekler ve olay belirli bir aralık için tetiklenmemişse işleyici işlevini çağırır. Bu, bir geri aramayı yalnızca yeniden boyutlandırma olayı veya benzeri bir gecikmeden sonra tetiklemek istiyorsanız kullanışlıdır.

Güncellemeler için github deposunu kontrol etmek önemlidir!

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

Son olarak fazladan bir parametre iletebilmeniz dışında, diğer herhangi bir onveya bindolay işleyicisi gibi kullanın :

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

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

(bu demo resizeyerine kullanıyor scroll, ama kimin umurunda ?!)


Hala% 100 doğru değil: bazen kullanıcı 250 ms sonra bile durur ve kaydırmayı sürdürür
Arman Bimatov

Bu kod harika çalışıyor, ancak jquery ui'nin otomatik tamamlama parçacığını tamamen bozdu.
kkazakov

@ArmanBimatov o zaman kullanıcı kaydırmaya devam ettikçe kabul edilecek, bu kulağa hoş geliyor, değil mi?
godblessstrawberry

Bu zaman aşımı yalnızca kaydırma olayları durduğunda tetiklenir ve kullanıcı kaydırmayı bıraktığında DEĞİL. Kullanıcı parmağını fareden kaldırabilir ve kaydırma hızına bağlı olarak kaydırma birkaç saniye devam edebilir. Bu çözüm, kullanıcı kaydırmayı durdurduğunda size bir gösterge vermeyecektir.
AndroidDev

1
@abzarak bu soyut yardımcı hiçbir durumda mükemmel değil! Yakın zamanda github-repo'yu nedenlerden dolayı güncellemedim - bu korkunç bir fikirdi. Bunun yerine "kısma" veya "geri alma" sarmalayıcı işlevi kullanın. Bunu başka bir yerde de not etmeliyim! :)
yckart

49

JQuery gaz kelebeği / geri tepme kullanma

jQuery debounce bu gibi problemler için iyi bir yöntemdir . jsFidlle

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

İkinci parametre "at_begin" bayrağıdır. Burada hem "kaydırma başlangıcı" hem de "kaydırma bitişi" nde kodun nasıl çalıştırılacağını gösterdim.

Lodash'ı kullanma

Barry P'nin önerdiği gibi, jsFiddle , altçizgi veya lodash , her biri biraz farklı apis'lere sahip olan bir dezavantaja sahiptir.

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

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

Aynı anda normal bir kaydırma işlevini kullanmak mümkün mü? $ (pencere) .scroll (işlev () {...});
Daniel Vogelnest

Elbette, jQuery bir olaya istediğiniz kadar işleyiciyi bağlayacaktır.
Sinetheta

Bunu güncellediğiniz için teşekkürler @BarryP Jsfiddle ayrıca lo-dash sağlar, böylece harici bağlantıdan kaçınabilirsiniz jsfiddle.net/qjggnyhf
Sinetheta

Bilginize, hızlı parşömenlerin geri dönmediği sorunlar yaşıyordum. Görünüşe göre "STOPPED" geri bildirimine birkaç milisaniye eklemeniz gerekiyordu, aksi takdirde bazen STOPPED'in STARTED'dan önce tetiklendiği bir yarış durumuna neden oluyor ve sonuçta hala kaydırıyormuşsunuz gibi öğe takılı kalıyor. Sırasıyla 150 ve 160 yaptım ve hile yapıyor gibiydi.
CodeChimp

Teşekkürler @ CodeChimp, bu harika, ancak uç durumları 16 defadan 15'ini düzelterek ele almaktan endişeleniyordum;) Belki de tüm mantığı içinde olan tek bir işleyici en güvenli olurdu. Kendinizi leadingve trailingkendinizi kontrol edin , sonra hiçbir kafa karışıklığı olmayacağından emin olun.
Sinetheta

9

Rob W, burada orijinal postama benzer bir gönderi olan başka bir gönderiye göz atmamı önerdi. Bunu okuyarak bir siteye bağlantı buldum:

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

Bu aslında kendi ihtiyaçlarım için küçük bir değişiklik yaptıktan sonra sorunumu çok güzel bir şekilde çözmemize yardımcı oldu, ancak her şeyden öte, yoldan çıkmamı sağladı ve kendi başıma çözmem için yaklaşık 4 saat kurtardım.

Bu gönderinin bir değeri var gibi göründüğünden, yazarın siteyle farklı bir yöne gitmeye karar vermesi ve bağlantıyı kaldırması durumunda, geri gelip orijinal olarak belirtilen bağlantıda bulunan kodu sağlayacağımı düşündüm.

(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

Yukarıdaki yorumlardan bazılarına, bir zaman aşımını dinlemenin yeterince doğru olmadığı konusunda hemfikirim, çünkü kaydırma çubuğunu kaydırmayı bıraktığınız zaman yerine yeterince uzun süre hareket ettirmeyi bıraktığınızda tetiklenecektir. Bence daha iyi bir çözüm, kullanıcının kaydırma yapmaya başlar başlamaz fareyi bırakmasını (mouseup) dinlemektir:

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

ve bunun çalıştığına dair bir örnek bu JSFiddle'da görülebilir.


2
Bu harika görünüyor, ancak bir izleme dörtgeninde veya bir kaydırma tekerleğinde 2 parmak hareketiyle kaydırıyorsanız, fareyi yukarı kaldırmayın. Bu muhtemelen kaydırmanın en yaygın yoludur ve bu da onu sorunlu hale getirir.
Adam

1
İyi bir nokta. Ancak potansiyel olarak bunun için birkaç düzeltme var. Jquery'nin 'fare tekerleği' olayını kullanma veya önce fareyi indirdiyse takip etme ve başkalarının önerdiği şekilde bir zaman aşımı yaklaşımı kullanma. Ancak, fare tekerleği olayları için diğer yanıtların bir kombinasyonunu kullanmanın ve kaydırma çubuğu sürükleme için bu yanıtın en doğru sonuçları vereceğini düşünüyorum
Theo

3

Aşağıdakilerin satırları boyunca her 500 ms'de bir çalışan bir aralık ayarlayabilirsiniz:

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

Bu kodu test etmedim, ancak ilke çalışmalı.


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

Başlangıç ​​ve bitiş yeteneğine sahip çok küçük versiyon


1

Tamam bu daha önce kullandığım bir şey. Temelde sonuncusuna bir hakem gibi görünüyorsun scrollTop(). Zaman aşımınız düzeldiğinde, akımı kontrol edersiniz scrollTop()ve aynıysa kaydırmayı tamamlamış olursunuz.

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

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

  currentScrollTop = $(this).scrollTop()
)

1

Kaydırma başlangıcını kontrol eden ES6 stili de.

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

Kullanımı:

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

Buna Hala İhtiyacı Olanlar İçin Çözüm İşte

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

Bu çalışmalı:

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

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

0

Bunu şu şekilde halledebilirsiniz:

    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

Bu, global bir zamanlayıcı kullanarak 1 milisaniyeden sonra (veya değiştirdikten) sonra kaydırma durmasını algılar:

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.
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.