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

8

我正在执行 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;});

这是一个简单的代码,每秒钟“允许”一次鼠标滚动事件。
如果我快速地触摸触控板进行滚动,鼠标滚轮事件将被触发约300次。一秒钟的条件可以让3个事件发生。我的手指在触控板上的时间远远不到一秒钟。
通过这个测试,我发现即使我的手指已经离开触控板,鼠标滚轮事件仍然会持续触发(几乎连续3秒)。
有没有JavaScript函数或绕过/技巧/黑客来避免这种行为呢?
也许像触控板的onTouchEnd事件那样的东西?
2个回答

1

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

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/


1
可能使用触摸事件,具体来说是触摸结束事件。 - IeuanG
1
根据@Gothdo阅读文档,触摸事件将来应该可以支持轨迹板:“_触摸事件提供了解释在触摸屏幕或轨迹板上的手指(或笔)活动的能力_”。 - GlabbichRulz
1
看起来触摸板目前在大多数情况下都不受支持,但是使用这些事件,你可能将来能够实现你想要的功能,希望如此。不利的一面是,我们不知道这些事件何时会被浏览器支持轨迹板。另外,由于某些网站存在问题,火狐浏览器似乎已经禁用了这个功能。我会把这个答案添加到以后搜索这个问题的人们的答案中。 - IeuanG
1
我还添加了一个 jsfiddle,当这些事件完全受支持时应该能正常工作。不过我的滚动停止代码感觉不太对。 - IeuanG
1
太好了!感谢你修复那段代码。你介意我把它加到答案里吗?我宁愿有一个可用的演示供未来读者查看,而不是一个半可用的演示。 - IeuanG
显示剩余3条评论

1

1
仅仅区分触摸板事件和滚轮事件是不够的,对吧?你还需要找到一种方法来确定事件是否由惯性滚动触发,这可能需要让触摸板开始触发“touchstart”和“touchend”事件。或者我没有考虑全? - DoctorDestructo
1
@DoctorDestructo 是的,你说得对。我假设指针事件将为触摸板提供touchstarttouchend事件。 - Michał Perłakowski
两年后,我们现在得到了一个二级编辑草案,虽然它的发展速度很慢,但我很感激总算有了一些进展 :) https://www.w3.org/TR/pointerevents2/ - GlabbichRulz
2
三年后,我们现在拥有了3级编辑草案。伙计们,我们快要成功了!https://w3c.github.io/pointerevents/ - 已经在所有主要浏览器中具备完整的浏览器支持或者使用polyfill:https://caniuse.com/#feat=pointer 。我可能很快会测试一下是否可以使用这个API解决我的问题。 - GlabbichRulz
1
@GlabbichRulz 很不幸,这并没有帮助,因为触摸板事件仍然被浏览器/操作系统作为鼠标事件发出(不知道哪一个是罪魁祸首)... - Piou

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接