【问题标题】:Event when user stops scrolling用户停止滚动时的事件
【发布时间】:2011-04-11 16:58:14
【问题描述】:

当用户滚动页面时,我想做一些花哨的 jQuery 东西。但是我不知道如何解决这个问题,因为只有scroll() 方法。

有什么想法吗?

【问题讨论】:

    标签: javascript jquery scroll jquery-events


    【解决方案1】:

    您可以使scroll() 有一个超时,每次用户滚动时都会被覆盖。这样,当他在一定的毫秒数后停止时,您的脚本就会运行,但如果他同时滚动,计数器将重新开始,脚本将等到他再次滚动完成。

    更新:

    因为这个问题又得到了一些行动,我想我不妨用一个添加 scrollEnd 事件的 jQuery 扩展来更新它

    // extension:
    $.fn.scrollEnd = function(callback, timeout) {          
      $(this).on('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://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
    
    <div style="height: 200vh">
      Long div
    </div>

    【讨论】:

    • 1000 毫秒比 250 毫秒要好很多
    • 这种技术也称为事件去抖动。
    • 它甚至可以在 100 毫秒内运行良好? 不要使用 10 毫秒,否则滚动会卡住。顺便说一句,您也可以在 DIV 上绑定 scrollEnd 扩展。在这里帮助了我:stackoverflow.com/q/71239600/1066234
    【解决方案2】:

    这是一个使用 setTimeout 在用户停止滚动时触发函数的简单示例:

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

    当滚动事件触发时计时器被清除。一旦滚动停止,就会触发刷新功能。

    或作为插件:

    $.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;
    };
    

    在 div 上的最后一个滚动事件 100 毫秒后触发回调(带有命名空间):

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

    我用它来滚动和调整大小。

    【讨论】:

    【解决方案3】:

    以下是基于上述相同想法的另一个更通用的解决方案:

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

    【讨论】:

    • 另外,您可以通过将值 500 更改为较低的值 (~~100) 来控制触发此事件的速度
    【解决方案4】:

    我也需要实现讨论过的 onScrollEnd 事件。 使用计时器的想法对我有用。

    我使用 JavaScript 模块模式来实现这个:

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

    希望这会帮助/激励某人

    【讨论】:

      【解决方案5】:

      为什么这么复杂?正如文档指出的那样,http://jsfiddle.net/x3s7F/9/ 有效!

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

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


      注意:Windows Chrome 上的scroll 事件与所有其他事件不同。您需要快速滚动才能获得与例如结果相同的结果。法郎。看https://liebdich.biz/back.min.js的“X”函数。

      我的how many ms a scroll event 测试的一些发现:

      • Safari、Mac FF、Mac Chrome:约 16 毫秒一个事件。
      • Windows FF:约 19 毫秒一个事件。
      • Windows Chrome:当滚动缓慢时,一个事件最多约 130 毫秒。
      • Internet Explorer:最多约 110 毫秒的事件。

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

      【讨论】:

      • 实际上,这很好用。不幸的是,在演示中使用滚动条不起作用,尽管我相信这只是因为fadeIn 函数。将不得不进行更多测试以找出是否还有更多错误,但做得好,效果很好!对于这么小的任务,其他解决方案要复杂得多。
      • 谢谢。对未发表评论的投票者:“现在好点了吗?” %)P
      • 现在,如果我只想保持向上滚动事件的条件,那么如何检测向上滚动?你能帮忙吗?
      【解决方案6】:

      没有“scrollEnd”这样的事件。我建议您使用setInterval 每隔一段时间(例如,200 毫秒)检查一次scroll() 返回的值,并记录当前值和先前值之间的增量。如果 delta 变为零,您可以将其用作您的事件。

      【讨论】:

      • 除非您保留对处理程序的引用并在 delta 变为零时调用 clearInterval,或者干脆改用 setTimeout
      • 偶然否决这个答案,现在是locked...抱歉
      【解决方案7】:

      滚动启动和滚动停止功能是 jquery mobile 的一部分。

      使用滚动停止的示例:

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

      希望这对某人有所帮助。

      【讨论】:

      • 这对我来说似乎并不火 :(
      • @RatherNotsay 它不适合你?我在生产中有这个,它似乎工作得很好。您是否包含了 jquery 的移动版本?和jquery不一样。
      • 我肯定有 JQuery Mobile,但它可能是缺少该组件的自定义构建?我现在已经继续前进,但如果我重新访问,我会更新。
      【解决方案8】:

      我从我拼凑在一起的一个快速片段中提取了一些代码,作为示例(请注意,scroll.chain 是一个包含两个数组 start 和 end 的对象,它们是回调函数的容器)。另请注意,我在这里使用的是 jQuery 和下划线。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-15
        相关资源
        最近更新 更多