浏览器滚动事件在 iOS 和 Android 设备上触发的频率不够高

Posted

技术标签:

【中文标题】浏览器滚动事件在 iOS 和 Android 设备上触发的频率不够高【英文标题】:Browser scroll event doesn't fire often enough on iOS and Android devices 【发布时间】:2014-02-03 10:28:33 【问题描述】:

我正在使用 jQuery、greensock 和 scollorama 开发一个单页网站。

它并不完全需要支持移动浏览器,但如果它可以在 iPad 上运行那就太好了 - 因此我开始在各种手机和平板电脑上进行测试。

我遇到的问题是 scrollorama 依赖于经常触发的滚动事件,因为这是动画所挂钩的 - 但是,当使用触摸屏时,浏览器似乎只在您启动时触发滚动事件拖动和停止时 - 这在 Opera Mini、Chrome、Safari、FF Mobile 中是一致的。

为了让我的页面至少部分工作,我需要想出一些东西来让我更频繁地触发滚动事件 - 有人知道怎么做吗?

P.S 我已经尝试按照 scrollorama 文档的建议使用 iScroll,但这并没有奏效,反而破坏了动画并使滚动变得不可能——我确信插件本身可以工作,但它似乎不能很好地与我已经得到了什么。我正在寻找比插件更少的东西,只是一个 sn-p 来理想地触发滚动事件。

TL;DR

带有触摸屏的设备在拖动过程中似乎只触发一次或两次 javascript 滚动事件。我可以在 JS 或 jQuery 中做一个简单的补丁来更频繁地触发滚动事件吗?


更新:我已经尝试像这样连接到触摸事件并触发浏览器滚动:

    $(document).on('touchstart touchend touchmove', function()
        $(window).trigger('scroll');
    );

这似乎在使用 Firefox 的 android 上给了我更好的结果,尽管我认为它没有像我希望的那样频繁地触发它总比没有好。

我会在其他浏览器中测试,看看是否有帮助。

更新 2:

上面的代码对 Android 上的 FF 有很大帮助,但对 iPhone 没有帮助。我尝试为 iPhone 触发的手势事件添加处理程序,但没有改变。

$(window).on('touchstart touchend touchmove mousewheel touchcancel gesturestart gestureend gesturechange orientationchange', function()
        //alert($(window).scrollTop());
        $(window).trigger('scroll');
    );

【问题讨论】:

【参考方案1】:

iOS 8 之前的版本:

这不是足够触发滚动事件的问题。相反,ios 上的浏览​​器在滚动手势中间停止刷新(即“重新绘制”)屏幕。

Safari WebKit 是根据 Apple 政策强制在所有 iOS 浏览器中使用的 html 呈现组件,它会在滚动手势期间停止重新绘制以延长电池寿命并减少热量。请注意,JavaScript 在滚动手势期间确实会继续在后台正常运行,即使屏幕无法反映滚动手势期间对 DOM 所做的任何实时更改。手势一结束,就会立即触发一个绘制事件,并且屏幕会更新。但是,计时器循环(例如通过setInterval 设置的那些)不会在滚动手势期间触发。

还值得注意的是,如果您在开始滚动时非常缓慢地移动手指,则滚动手势要等到您将手指从其起始位置移开大约 10 个像素后才会生效。在这 10 像素半径内移动期间,屏幕会持续瞬间刷新。当 WebKit 确定您的手指移动到足以启动滚动时,屏幕刷新将被禁用,直到滚动手势结束。

这个问题不会影响“某些”网页或 JavaScript 库的原因是它们有效地“冻结”了页面的滚动,而是通过拦截触摸事件然后相应地调整 body.scrollTop 属性来模拟滚动。他们通过将事件处理程序附加到onscroll 事件来冻结页面的滚动,并从事件处理程序中发出event.preventDefault() 命令。

iOS 8 及更高版本:

Apple 正在让 iOS 8 中的滚动事件更加流畅:

http://developer.telerik.com/featured/scroll-event-change-ios-8-big-deal/

【讨论】:

我很高兴听到这种情况开始发生变化,我从未找到解决方法,只是保持原样。如果运行 iOS8 的设备刚刚开始工作就好了 :) @G.Mart 不幸的是我从来没有找到一个,我们放弃了那个项目,只是不能很好地支持触摸屏。 18 个月后现在可能更有可能,因为我注意到 scrollorama 有一个重大更新 - 也许这会对你有所帮助:johnpolacek.github.io/superscrollorama/simpledemo_mobile.html 有没有办法检测滚动时屏幕没有刷新?【参考方案2】:

在我这边,我禁用了 ios Chrome 的功能

// Fix Chrome iOS
if(!navigator.userAgent.match('CriOS'))
    // do my stuff here      

我不知道滚动时不刷新屏幕的导航器的完整列表。如果有人可以提供帮助;)

【讨论】:

以上是关于浏览器滚动事件在 iOS 和 Android 设备上触发的频率不够高的主要内容,如果未能解决你的问题,请参考以下文章

如何从 IOS Safari 中的 touchmove 事件中检测滚动画布

转让iframe在iOS设备手机浏览器上支持滚动

如何使用 Modernizr 检测对即时滚动事件的支持?

无法在 Android 设备上的 Javascript 中获取触摸事件的坐标

网页上的水平滚动在 iOS 中不起作用

JQuery 移动 IOS 设备如何在 web 上删除默认滚动