用户停止滚动时的事件

Posted

技术标签:

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

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

有什么想法吗?

【问题讨论】:

【参考方案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 扩展。在这里帮助了我:***.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
);

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

【讨论】:

这被称为“去抖动”方法。更多信息(和可重复使用的功能)在这里:davidwalsh.name/function-debounce【参考方案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;

【讨论】:

以上是关于用户停止滚动时的事件的主要内容,如果未能解决你的问题,请参考以下文章

如何实现滚动捕捉停止:总是;

没有jQuery mobile的滚动停止事件[重复]

iPhone:单击开始视频录制按钮时的事件?

他们会修复移动滚动事件吗?

停止弹出对话框的 touchmove 事件

Egret 组件顺序排列时的 drawCall 优化思路