スマホ用Webページにおける、タップやスクロールのイベント発火タイミング
こんにちは。id:naosuke2dx です。
梅雨でジメジメがすごい今日このごろ、皆様いかがお過ごしですか。
さて、今日の話はWebページ等でのイベント発火のタイミングについてです。
自分も何度か引っかかってそのたびに調べていたので、メモ的な目的もあります。
そもそもイベントってなんだっけ
「ユーザを始めとしたあらゆるものが引き起こした、何らかのアクション」のことをイベントと言います。
例えば、ユーザがクリックをした場合、そのクリックがイベントであるということです。
JavaScriptでは、このイベントをトリガーとして、様々な処理を行うことができます。
例えば、クリックした要素を変える、マウスが要素の上に乗っかったらその要素に影をつけてみるなどなど…。
有名どころのイベントだと、このようなものがあります。
標準イベントの他に、イベントを独自定義することもできます。
スマホ(タッチパネル機器)特有のイベント
さて、じゃあスマホだとこのイベントはどうなるのかというと、当然存在します。
ただ、標準イベントのうちマウス系のイベントは当然使うことができません。
(マウスを繋いでスマホを使うエクストリームな例は除きます)
このため、W3Cによってそれを補完するイベントが勧告され、現在ではそれを利用しています。
W3Cの勧告によれば、以下の4つがあるそうです。
touchstart
発火タイミング: タッチが始まったときtouchend
発火タイミング: タッチが終わったときtouchmove
発火タイミング: タッチして動かしてるときtouchcancel
発火タイミング: タッチが中断されたとき(端末そのものの自動回転等)
スマホのタッチ発火イベント
スマホ特有のイベントで、4つのイベントを挙げました。
実際には、スマホではこの4つ+ブラウザでサポートされているイベント が対応しています。
ここで疑問に思うことが1つ出てきます。
「あれ、touch系とclickってほとんど一緒じゃないの?」
はい。これが本題です。
実際、自分はここでなんかもっさりしてるなーと思いつつスルーしてました。
スマホでは、イベント発火は以下の順序で行われるそうです。
touchstart ↓ touchend ↓ click
マウスだとclickイベント1つだけで終わるところ、スマホだと3つのイベントが発火します。
加えて、スマホの場合はclick
イベントはタップ後に300msの遅延があって、ようやく発火します。
これは、ダブルタップ(doubleclick
)の判定のための遅延で、1回目のタップ後、300ms以内にタップを認識した場合、doubleclick
が発火する仕掛けになっています。
特にタップがない場合は、300msの虚無ののち、click
が発火します。
それが、この章の冒頭にあった「なんかもっさりしてるなー」の原因でした。
解決法
解決するには、fastclick.js
というライブラリを入れるのがいいらしいとのこと。
仕組みとしては、touchstartイベントの発火を強制的にキャンセルし、すぐにclickイベントを発火してくれます。 これを使うことで、もっさり感がなくなって、タップしてすぐにクリックイベントが発火してくれて、とってもハッピーな感じです。
scrollイベントの発火タイミング
上の紹介では出てきませんでしたが、scroll
イベントというものもあります。
これは名前から想像できるように、スクロールが発生したときに発火するイベントです。
これもまた少し曲者でした。
スマホでも、当然scroll
イベントは発火をしてくれて、たとえば「画面幅以上スクロールした場合はメニューバーを画面上部に貼り付ける」等の処理の際に利用したりします。
しかし、スクロールを開始したにも関わらずこのイベントが発火しないという現象が、iOSで発生します。
原因は、慣性スクロール
でした。
iOSやAndroidでは、慣性スクロール
というものが実装されています。
これは、指を素早く動かして離したときに、スクロールが急に止まらず、慣性が働いているかのように動く機能のことです。
これによって、操作可能範囲が限られたスマホでも、効率的にスクロールできる…らしいです。
で、iOSのSafariでは、この慣性スクロールが停止したときにscroll
イベントが1回だけ発火する仕様とのこと。
ちなみに、AndroidはPCと同様にスクロール中は連続的にscroll
イベントが発火するそうです。
この解決方法はまだ見つかっていないので、いい案があれば教えていただければと思います。
まとめ
今回は、スマホのウェブページにおけるイベントの発火タイミングについてまとめました。
スマホはOSや機種によって微妙な違いがあって、レイアウト崩れなどこまごまとした問題がいろいろ出てきて大変ですね。
余談ですが、この記事を書いている間、Macがtouchend
をtouched
に自動スペル修正をしてくれて非常に大変でした。