互換性が向上し、スムーズなタッチ操作を実現

モバイルウェブアプリは、タップ操作にスムーズに反応してスクロールするアプリが求められます。開発は簡単ですが、残念ながら、モバイル ウェブブラウザがスクロール中のタップイベントにどのように反応するかは、TouchEvent 仕様の実装の詳細として残されています。そのため、アプローチは大きく 4 つのカテゴリに分類できます。この状況は、スムーズなスクロールとデベロッパーによる制御の維持との間の根本的な緊張関係を示しています。

タッチイベント処理の 4 つのモデル

ブラウザ間の動作の違いは、4 つのモデルに分類されます。

  1. 通常の同期イベント処理

    タッチ移動イベントはスクロール中に送信され、タッチ移動の処理が完了するまで各スクロール更新がブロックされます。これは、理解が最も簡単で最も強力な方法ですが、スクロール中の各フレームがメインスレッドでブロックされるため、スクロールのパフォーマンスには不利です。

    ブラウザ: Android ブラウザ(Android 4.0.4、4.3)、モバイル Safari(div をスクロールしているとき)

  2. 非同期タッチ移動処理

    スクロール中に touchmove イベントが送信されますが、スクロールは非同期的に進行できます(スクロールが開始された後、touchmove イベントは無視されます)。これにより、イベントの「二重処理」が発生する可能性があります。たとえば、ウェブサイトが touchmove で何かを行い、イベントで preventDefault を呼び出してブラウザに処理しないように指示した後も、スクロールが続行される場合があります。

    ブラウザ: モバイル Safari(ドキュメントのスクロール時)、Firefox

  3. スクロール中にタッチ移動が抑制される

    スクロールの開始後に touchmove イベントは送信されず、touchend イベントが送信されるまで再開されません。このモデルでは、静止したタップとスクロールを区別することが困難です。

    ブラウザ: Samsung ブラウザ(mousemove イベントが送信される)

  4. スクロール開始時のタップキャンセル

    スクロールの滑らかさとデベロッパーによる制御の両方を実現することはできません。このモデルでは、ポインタ イベント仕様のセマンティクスと同様に、スムーズなスクロールとイベント処理のトレードオフが明確に示されています。指の操作をトラッキングする必要があるエクスペリエンス(プルして更新など)は使用できません。

    ブラウザ: Chrome デスクトップ M32 以降、Chrome Android

変更の理由

現在、Android 版 Chrome では Chrome の古いモデル(スクロール開始時の touchcancel)が使用されています。これによりスクロール パフォーマンスは向上しますが、デベロッパーの混乱を招くことになります。特に、一部のデベロッパーは touchcancel イベントやその処理方法を認識しておらず、ウェブサイトが破損する原因となっています。さらに重要なことに、プルして更新非表示バースナップポイントなど、UI スクロール エフェクトと動作のクラス全体を適切に実装することは困難または不可能です。

Chrome では、これらのエフェクトをサポートするためにハードコードされた機能を追加するのではなく、デベロッパーがこれらのエフェクトを直接実装できるようにするプラットフォーム プリミティブの追加に重点を置いています。この考え方について詳しくは、A Rational Web Platform をご覧ください。

Chrome の新しいモデル: スロットル付き非同期タッチ移動モデル

Chrome では、スクロール時の他のブラウザ用に記述されたコードとの互換性を高め、スクロール中の touchmove イベントの取得に依存する他のシナリオを有効にするように設計された新しい動作が導入されます。この機能はデフォルトで有効になっています。次のフラグ chrome://flags\#touch-scrolling-mode を使用して無効にできます。

新しい動作は次のとおりです。

  • 最初の touchmove は同期的に送信され、スクロールをキャンセルできます。
  • スクロール中にアクティブになった場合
    • touchmove イベントは非同期で送信されます。
    • 200 ミリ秒あたり 1 イベントにスロットリングされる、または CSS の15 ピクセルの勾配領域を超えている
    • Event.cancelablefalse の場合
  • それ以外の場合、アクティブなスクロールが終了したとき、またはスクロールの上限に達したためにスクロールが不可能になったときに、タッチ移動イベントが通常どおり同期的に発生します。
  • ユーザーが指を離すと、touchend イベントが常に発生します。

Chrome for Android でこのデモを試し、chrome://flags\#touch-scrolling-mode フラグを切り替えて違いを確認できます。

ご意見をお寄せください

非同期タッチ移動モデルは、クロスブラウザの互換性を向上させ、新しいクラスのタッチ操作効果を可能にする可能性があります。デベロッパーの皆様のご意見をお聞かせください。また、この機能を使ってどのようなクリエイティブなことができるか、ぜひお知らせください。