iPhone/Androidにタッチ!
stats.js (https://github.com/mrdoob/stats.js) という、JavaScriptでfpsもどきの値を出すライブラリをiPhone/Androidで試していた時に気づいたんだけど、iPhone/AndroidのWebKitではデフォルトのスクロール中はsetIntervalの監視が無効になっているっぽい。
具体的には、例えば setInterval(function() { count++; }, 1000); みたいなことをやっているページがあってとして
1. タッチ開始
2. 指を動かす
3. タッチ終了
4. 慣性スクロール
の流れで、4.が完全に終わるまでcountの値は変わらない。また、実行キューに入っていたものがスクロール後に一気に実行されるというわけでもない。完全にtimerが止まっている。
一瞬「指を置いて動かしている間はJSの実行は全く行われないのかな?」と思ったが、それだとtouchmoveとかにbindしたevent handlerが全く実行されないことになってしまう。そんなアホな。
そんなアホなことは流石になかったが、はて。私たちは、touch eventのevent handlerの実行だけが許されたイヌカレー空間に居る、とでもいうのだろうか。
setInterval及び各event handler(touchstart, touchmove, touchend, scrollにbind)の中でxhrでリクエスト投げて眺めてみると、
1. タッチ開始 -> touchstart, timer停止
2. 指を動かす -> touchmove
3. タッチ終了 -> touchend (iOS: この時点でtimer再開)
4. 慣性スクロール -> scroll (Android: scrollが完全に終了後 timer再開)
のような関係になっているように見える。iOSがタッチ終了時にtimer再開していると予想したのは、setIntervalによってenqueueされていた処理が一気に実行されたっぽい感じにスクロール終了後バラバラッとリクエストが来たので。
手元にあるiPhone 3GS(iOS 4.2.1)とHTC evo(Android 2.2.1)でしか比べてないが、iOSとAndroidでは同じ指の動かし方をしても全くeventの発行のされ方が違っていて
iOSのほうは
touchstart touchmove touchmove touchmove touchmove touchmove touchmove touchend scroll
という感じにeventが発行されるのに対して、
Androidだと
touchstart touchmove touchmove touchend scroll scroll scroll scroll scroll scroll scroll scroll scroll scroll scroll scroll scroll . . .
みたいな感じでtouchmoveの数がiPhoneよりかなり少なく、scroll eventおよび慣性スクロールによる移動量がiOSのそれよりかなり大きい。前者はHW的な感度の問題なのか、それともブラウザ側の問題なのか…
eventの発行のされ方がここまで違うと、touchmove or scroll eventの粒度の細かさに依存した処理を書いてしまうと「あれれー、おかしいなー?おじさん、iPhoneとAndroidで動作が全然違うよ?」みたいなコナン君になってしまうかもしれない。