iOS Safariで全体のscrollイベント取得


モバイルサイトで無限スクロールを取り入れようとしてJavaScriptで実装してみた…のですが、AndroidはいいとしてiOSですんなり動かなくなってしまいました。調査して回避策も見つけたので、それを含めて書き進めていきます。

素直にできなくて

無限スクロール実装というのは、分解すれば3要素から成っています。

  1. スクロール中にブラウザの高さをチェックする
  2. 適切な高さに来ていれば次のコンテンツを読み始める
  3. 読み込んだコンテンツを末尾に追加

ということですが、iOSで素直に実装してみると、ブラウザの末端に当たってから読み込みを開始する、なんていう現象が多発してしまいました。調べてみると、iOSのSafariでは、ブラウザ全体のスクロール中にJavaScriptが止まってしまうらしく、そのままではうまくいかなさそうな感じでした。

ライブラリはあるけれど

他のQiita記事でも紹介されていたiScrollというライブラリがあるとのことだったので、試してみることにしました。このライブラリ、動作原理としては

  1. すべてのスクロールをJavaScriptで乗っ取って、ブラウザ側には伝えない。
  2. スクロール量を自前で計算して、自前で表示を動かす

というようなものです。使ってみると…かなり重くて、スクロール感はネイティブのものに対して大きく見劣りするものでした。ブラウザ内アプリのような感じで短いページなら実用できるのかもしれませんが、無限スクロールのような長いページに取り入れると、ページ全体の操作が重すぎて操作感が台無しとなってしまいました。

探し求めれば道が開けた

さらに調べてみると、「ページ全体のスクロールではJavaScriptが止まるけど、ページの一部のスクロールなら問題なく動作する」という情報が得られました。そこで、

  1. ブラウザ全体に広がるような<div>を作る
  2. overflow-y:auto;-webkit-overflow-scrolling:touchというようなCSSをかけて、慣性スクロールするようにする
  3. コンテンツ全体をこの<div>の中に移動させる
  4. ブラウザ全体がスクロールしないように、CSSやJavaScriptで調整する
  5. scrollイベントはこの<div>へ割り当てる

というようにすることで、ブラウザネイティブなスクロールを行いつつ、JavaScriptイベントも発生する環境を作ることができました。