【问题标题】:Disable Predictive Scrolling - Mousewheel (OnScroll) Event fires too often (Touchpad)禁用预测滚动 - 鼠标滚轮 (OnScroll) 事件触发太频繁(触摸板)
【发布时间】:2020-04-18 22:12:23
【问题描述】:

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

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

我从移动触控设备中了解到这种行为。该功能称为“Predictive Touch” - 如果您的手指移动在抬起之前有足够的加速度,则滚动会继续。

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

为了调试这个案例,我使用了以下代码:

/* 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 jquery touch jquery-events mousewheel


    【解决方案1】:

    要实现这一点,您必须区分鼠标滚动事件和触摸板事件,这(目前)还不能使用 JavaScript。已经有人问过How to capture touch pad input

    Pointer Events 目前处于编辑草稿状态,尚未被任何浏览器支持。另见touch events docs on MDN

    【讨论】:

    • 仅仅区分触摸板事件和滚轮事件是不够的,不是吗?您仍然需要一种方法来确定事件是否由惯性滚动触发,这可能需要触摸板开始触发touchstarttouchend 事件。还是我没有考虑清楚?
    • @DoctorDestructo 是的,你是对的。我假设指针事件将为触摸板提供touchstarttouchend 事件。
    • 两年后,我们现在得到了一个 2 级编辑的草稿,很遗憾它的发展速度很慢,但我很感激有进步:) w3.org/TR/pointerevents2
    • 三年后,我们现在有了 3 级编辑草稿。伙计们,我们快到了! w3c.github.io/pointerevents - 已经在所有主流浏览器中提供完整的浏览器支持或 polyfill:caniuse.com/#feat=pointer。我可能会尽快测试是否可以使用此 API 解决我的问题。
    • @GlabbichRulz 不幸的是,这无济于事,因为触摸板事件仍然由浏览器/操作系统作为鼠标事件发出(不知道应该归咎于哪一个)......跨度>
    【解决方案2】:

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

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

    Demo

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

    【讨论】:

    • 可能使用touch events,特别是touchend事件。
    • @Gothdo 阅读docs,触摸事件在未来应该能够支持触控板:“触摸事件提供了在触摸屏或触控板上解释手指(或触控笔)活动的能力."
    • 在大多数情况下,目前似乎不支持触摸板,但是如果运气好的话,看起来您将来可以使用这些事件实现您想要的。不利的一面是,我们不知道触控板浏览器何时支持这些事件。由于某些网站的问题,这个功能在 Firefox 中看起来好像是 disabled。我会将此添加到将来搜索此内容的任何人的答案中。
    • 我还添加了一个 jsfiddle,当这些事件完全支持时应该可以工作。然而,我的滚动停止代码感觉不对。
    • 太棒了!感谢您修复该代码。您介意我将其添加到答案中吗?我宁愿为未来的读者提供一个工作演示,而不是一个半工作的演示。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-04
    • 1970-01-01
    • 2012-11-26
    • 1970-01-01
    • 2012-03-13
    相关资源
    最近更新 更多