更兼容、更流畅的触控

您和您的用户都希望移动 Web 应用能够响应触摸操作,并能顺畅地滚动屏幕。开发这些事件应该很容易,但是遗憾的是,移动网络浏览器如何在滚动期间响应触摸事件,仍是 TouchEvent 规范中的实现细节。因此,相关方法大致可分为 4 类。这种情况暴露了滚动流畅性与保持开发者控制权之间的基本冲突。

四种不同的触摸事件处理模型?

不同浏览器的行为差异分为四种模式。

  1. 正常的同步事件处理

    触摸移动事件会在滚动期间发送,并且每次滚动更新都会阻止发送,直到触摸移动处理完成为止。这种做法最简单易理解,功能最强大,但对滚动性能造成不良影响,因为这意味着滚动期间的每一帧都必须在主线程上阻塞。

    浏览器:Android 浏览器(Android 4.0.4、4.3)、移动设备 Safari(滚动 div 时)

  2. 异步 touchmove 处理

    触摸移动事件会在滚动期间发送,但滚动可以异步进行(滚动开始后触摸移动事件会被忽略)。这可能会导致对事件进行“双重处理”,例如,在网站执行了 touchmove 操作后继续滚动,并对事件调用 preventDefault,告知浏览器不要处理该事件。

    浏览器:移动版 Safari(滚动文档时)、Firefox

  3. 滚动时触摸移动已被禁止

    触摸移动事件不会在滚动开始后发送,并且在触摸结束事件发生后才会恢复。在此模型中,很难区分静止触摸和滚动。

    浏览器:Samsung 浏览器(已发送 mousemove 事件)

  4. 滚动开始时触摸取消

    您无法同时兼顾滚动流畅度和开发者控制这两个方面,而此模型明确采用了流畅滚动与事件处理之间的权衡取舍,类似于指针事件规范的语义。某些可能需要跟踪手指的体验(例如下拉刷新)则无法使用。

    浏览器:Chrome 桌面版 M32+、Chrome Android

为什么要更改?

Chrome(Android 版)目前使用的是 Chrome 的旧模式:滚动启动时触摸取消,这样可以提高滚动性能,但会导致开发者困惑。特别是,一些开发者不知道触摸取消事件或如何处理该事件,这已导致一些网站无法正常运作。更重要的是,一整类界面滚动效果和行为(例如下拉刷新隐藏栏贴靠点)很难或无法很好地实现。

Chrome 致力于添加可让开发者直接实现这些效果的平台基元,而不是添加专门的硬编码功能来支持这些效果。如需查看此理念的一般说明,请参阅合理的 Web 平台

Chrome 的新模型:Throttled Async Touchmove 模型

Chrome 推出了一种新行为,旨在改善与为其他浏览器编写的代码之间的兼容性,并支持那些依赖于在滚动时获取 touchmove 事件的其他场景。此功能默认处于启用状态,您可以使用以下标志 chrome://flags\#touch-scrolling-mode 将其停用。

新行为如下:

  • 首次触摸移动会同步发送,以便 取消滚动操作
  • 在主动滚动期间
    • touchmove 事件是异步发送的
    • throttled为每 throttled 1 个事件,或者如果超出了 CSS throttled 溢出区域
    • Event.cancelablefalse
  • 否则,当有效滚动终止或因达到滚动限制而无法实现时,touchmove 事件会照常同步触发
  • 当用户抬起手指时,始终会发生触摸结束事件

您可以在 Chrome(Android 版)中试用此演示,然后切换 chrome://flags\#touch-scrolling-mode 标志以查看差异。

请与我们分享您的想法

异步 Touchmove 模型能够提升跨浏览器兼容性,并支持一类新的触摸手势效果。我们衷心希望能了解开发者的想法,并了解您可以通过这些想法付出的创造性。