禁用预测滚动 - 鼠标滚轮 (OnScroll) 事件触发过于频繁(触摸板)

Disable Predictive Scrolling - Mousewheel (OnScroll) Event fires too often (Touchpad)

本文关键字:事件 于频繁 触摸 OnScroll 滚动 鼠标      更新时间:2023-09-26

我正在执行Javascript onScroll .我的代码适用于任何普通的计算机鼠标,但是当我使用笔记本电脑的触摸板时,我遇到以下情况:

  • 我的鼠标在手指移动滚轮时触发(大约 1 到 8 mousewheel事件。
  • 当两根手指触摸键盘时,我的触摸板会触发更多(~60)mousewheel事件,并在我的手指再次悬空后继续触发。

我从移动触摸设备上知道这种行为。该功能称为"预测触摸" - 如果您的手指移动在抬起之前有足够的加速度,滚动将继续。

我认为触摸板驱动程序正在设置这种"平滑滚动"行为。

为了调试这种情况,我使用了以下代码:

/* Handle Mouse-Wheel Scrolling */
var lastChange = +new Date();
$(window).bind('mousewheel',    function(e){
    console.log("mw");
    if(+new Date() - lastChange > 1000){
        console.log("mw allowed");
        if(e.originalEvent.wheelDelta > 0)  {/*go to previous*/}
        else{   /*go to next*/}
        lastChange = +new Date();
    }
return false;});

这是一个简单的代码,每秒"允许"一个鼠标滚动事件。

如果我进行快速触摸板滚动,mousewheel事件会触发~300次。一秒钟的条件是让 3 个事件发生。我的手指在触摸板上停留的时间远远不到一秒钟。

通过这个测试,我发现即使我的手指已经离开触摸板,mousewheel事件仍然被触发(几乎连续 3 秒)。

是否有Javascript函数或解决方法/技巧/黑客来避免此行为?

也许是触摸板的onTouchEnd活动?

要实现这一点,你必须区分鼠标滚动事件和触摸板事件,这在用JavaScript上还是不可能的。已经有人问到如何捕获触摸板输入。

指针事件当前处于编辑器草稿状态,尚不受任何浏览器支持。另请参阅 MDN 上的触摸事件文档。

编辑:这似乎不适用于触控板。一旦它们得到广泛支持,就可以使用触摸事件(特别是触摸结束事件)来实现。通过跟踪手指何时离开触控板,您可以防止页面在该特定点滚动。

https://jsfiddle.net/gLkkb5z0/3/

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

演示

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