jQuery scroll () mendeteksi ketika pengguna berhenti menggulir


109

Ok dengan ini ..

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

Saya tahu ketika seseorang menggulir dari apa yang saya pahami. Jadi dengan itu saya mencoba mencari cara untuk menangkap ketika seseorang berhenti. Dari contoh di atas Anda dapat melihat saya menghapus kelas dari sekumpulan elemen saat pengguliran terjadi. Namun, saya ingin mengaktifkan kembali kelas itu saat pengguna berhenti menggulir.

Alasan untuk ini adalah saya bermaksud mengadakan pertunjukan singgah saat halaman bergulir untuk memberi halaman efek khusus yang saya coba kerjakan. Tetapi satu kelas yang saya coba hapus saat menggulir bertentangan dengan efek itu karena itu adalah efek transparansi pada beberapa sifat.



Luar biasa, tidak persis sama, tetapi secara definitif sesuai dengan apa yang saya cari dan pada akhirnya membantu saya menyelesaikan masalah saya. Terima kasih.
chris

Jawaban:


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

Memperbarui

Saya menulis ekstensi untuk meningkatkan on-event-handler default jQuery . Ini melampirkan fungsi pengendali peristiwa untuk satu atau lebih peristiwa ke elemen yang dipilih dan memanggil fungsi pengendali jika peristiwa itu tidak dipicu untuk interval tertentu. Ini berguna jika Anda ingin mengaktifkan callback hanya setelah penundaan, seperti peristiwa pengubahan ukuran, atau semacamnya.

Penting untuk memeriksa github-repo untuk pembaruan!

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

Gunakan seperti penangan onatau bind-peristiwa lainnya, kecuali Anda dapat meneruskan parameter tambahan sebagai yang terakhir:

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

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

(demo ini menggunakan resizealih-alih scroll, tapi siapa peduli ?!)


Ini masih belum 100% akurat: terkadang pengguna berhenti dan melanjutkan pengguliran bahkan setelah 250 md
Arman Bimatov

Kode ini berfungsi dengan baik, tetapi itu benar-benar merusak widget pelengkapan otomatis ui jquery.
kkazakov

@ArmanBimatov maka itu akan dianggap sebagai pengguna terus menggulir, kedengarannya bagus, bukan?
Godblessstrawberry

Waktu tunggu ini hanya diaktifkan saat peristiwa gulir berhenti dan BUKAN saat pengguna berhenti menggulir. Pengguna dapat mengangkat jarinya dari mouse dan pengguliran dapat berlanjut selama beberapa detik tergantung pada kecepatan pengguliran mereka. Solusi ini tidak akan memberi Anda indikasi saat pengguna berhenti menggulir.
AndroidDev

1
@abzarak, penolong abstrak ini tidak sempurna, sama sekali! Saya belum memperbarui github-repo baru-baru ini, karena alasan - ini adalah ide yang buruk. Cukup gunakan fungsi pembungkus "throttle" atau "debounce" sebagai gantinya. Saya harus mencatatnya di tempat lain juga! :)
yckart

49

Menggunakan jQuery throttle / debounce

jQuery debounce bagus untuk masalah seperti ini. jsFidlle

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

Parameter kedua adalah flag "at_begin". Di sini saya telah menunjukkan bagaimana menjalankan kode baik pada "scroll start" dan "scroll finish".

Menggunakan Lodash

Seperti yang disarankan oleh Barry P, jsFiddle , underscore atau lodash juga memiliki debounce, masing-masing dengan apis yang sedikit berbeda.

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

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

Apakah mungkin untuk menggunakan fungsi gulir normal pada saat bersamaan? $ (window) .scroll (function () {...});
Daniel Vogelnest

Tentu saja, jQuery akan mengikat sebanyak mungkin penangan ke acara yang Anda inginkan.
Sinetheta

Terima kasih telah memperbarui @BarryP Jsfiddle ini juga menyediakan lo-dash sehingga Anda dapat menghindari tautan eksternal jsfiddle.net/qjggnyhf
Sinetheta

FYI, saya mengalami masalah di mana gulungan cepat tidak dapat kembali. Tampaknya Anda perlu menambahkan beberapa milidetik ke debounce "STOPPED", jika tidak hal itu menyebabkan kondisi balapan di mana, terkadang, STOPPED terpicu sebelum DIMULAI, dan Anda berakhir dengan item macet seolah-olah Anda masih menggulir. Saya membuat milik saya masing-masing 150 dan 160, dan tampaknya berhasil.
CodeChimp

Terima kasih @CodeChimp itu bagus, tapi saya khawatir tentang menangani kasus edge dengan memperbaikinya 15 dari 16 kali;) Mungkin satu penangan dengan semua logika di dalamnya akan paling aman. Periksa leadingdan trailingdiri Anda sendiri, lalu pastikan tidak ada kebingungan.
Sinetheta

9

Rob W menyarankan saya memeriksa posting lain di sini di tumpukan yang pada dasarnya adalah posting yang mirip dengan yang asli saya. Dari bacaan mana saya menemukan tautan ke situs:

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

Ini sebenarnya akhirnya membantu menyelesaikan masalah saya dengan sangat baik setelah sedikit menyesuaikan kebutuhan saya sendiri, tetapi secara keseluruhan membantu menghilangkan banyak kesalahan dan menyelamatkan saya sekitar 4 jam untuk mengetahuinya sendiri.

Melihat posting ini tampaknya memiliki beberapa manfaat, saya pikir saya akan kembali dan memberikan kode yang awalnya ditemukan pada tautan yang disebutkan, kalau-kalau penulis pernah memutuskan untuk pergi ke arah yang berbeda dengan situs dan akhirnya menghapus tautan tersebut.

(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

Saya setuju dengan beberapa komentar di atas bahwa mendengarkan waktu tunggu tidak cukup akurat karena itu akan memicu saat Anda berhenti menggerakkan bilah gulir cukup lama, bukan saat Anda berhenti menggulir. Saya pikir solusi yang lebih baik adalah mendengarkan pengguna melepaskan mouse (mouseup) segera setelah mereka mulai menggulir:

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

dan contoh kerjanya dapat dilihat di JSFiddle ini


2
Ini tampak hebat, tetapi jika Anda menggulir dengan gerakan 2 jari pada trackpad, atau scrollwheel, mouseup tidak akan diaktifkan. Ini mungkin cara paling umum untuk menggulir juga, yang membuatnya bermasalah.
Adam

1
Poin yang bagus. Tetapi kemungkinan ada beberapa perbaikan untuk itu. Menggunakan event 'mousewheel' jquery atau melacak if mousedown terlebih dahulu, dan menggunakan pendekatan timeout seperti yang disarankan oleh orang lain. Tetapi saya pikir menggunakan kombinasi jawaban lain untuk peristiwa roda mouse dan jawaban untuk menyeret bilah gulir ini akan memberikan hasil yang paling akurat
Theo

3

Anda dapat menyetel interval yang berjalan setiap 500 md atau lebih, di sepanjang baris berikut:

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

Saya belum menguji kode ini, tetapi prinsipnya harus berfungsi.


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

Versi yang sangat kecil dengan kemampuan awal dan akhir


1

Ok ini adalah sesuatu yang pernah saya gunakan sebelumnya. Pada dasarnya Anda terlihat memegang wasit sampai akhir scrollTop(). Setelah batas waktu Anda habis, Anda memeriksa arus scrollTop()dan jika sama, Anda selesai menggulir.

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

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

  currentScrollTop = $(this).scrollTop()
)

1

Gaya ES6 dengan pengecekan mulai bergulir juga.

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

Pemakaian:

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

Bagi Yang Masih Membutuhkan Ini Inilah Solusinya

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

Ini harus bekerja:

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

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

0

Inilah cara Anda menangani ini:

    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

Ini mendeteksi scroll stop setelah 1 milidetik (atau mengubahnya) menggunakan timer global:

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.
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.