Aqutras Members' Blog

株式会社アキュトラスのメンバーが、技術情報などを楽しく書いています。

スマホ用Webページにおける、タップやスクロールのイベント発火タイミング

こんにちは。id:naosuke2dx です。
梅雨でジメジメがすごい今日このごろ、皆様いかがお過ごしですか。

さて、今日の話はWebページ等でのイベント発火のタイミングについてです。
自分も何度か引っかかってそのたびに調べていたので、メモ的な目的もあります。

そもそもイベントってなんだっけ

「ユーザを始めとしたあらゆるものが引き起こした、何らかのアクション」のことをイベントと言います。
例えば、ユーザがクリックをした場合、そのクリックがイベントであるということです。

JavaScriptでは、このイベントをトリガーとして、様々な処理を行うことができます。
例えば、クリックした要素を変える、マウスが要素の上に乗っかったらその要素に影をつけてみるなどなど…。

有名どころのイベントだと、このようなものがあります。

qiita.com

標準イベントの他に、イベントを独自定義することもできます。

スマホ(タッチパネル機器)特有のイベント

さて、じゃあスマホだとこのイベントはどうなるのかというと、当然存在します。 ただ、標準イベントのうちマウス系のイベントは当然使うことができません。
(マウスを繋いでスマホを使うエクストリームな例は除きます)

このため、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 というライブラリを入れるのがいいらしいとのこと。

github.com

仕組みとしては、touchstartイベントの発火を強制的にキャンセルし、すぐにclickイベントを発火してくれます。 これを使うことで、もっさり感がなくなって、タップしてすぐにクリックイベントが発火してくれて、とってもハッピーな感じです。

scrollイベントの発火タイミング

上の紹介では出てきませんでしたが、scrollイベントというものもあります。
これは名前から想像できるように、スクロールが発生したときに発火するイベントです。
これもまた少し曲者でした。

スマホでも、当然scrollイベントは発火をしてくれて、たとえば「画面幅以上スクロールした場合はメニューバーを画面上部に貼り付ける」等の処理の際に利用したりします。 しかし、スクロールを開始したにも関わらずこのイベントが発火しないという現象が、iOSで発生します。 原因は、慣性スクロールでした。

iOSやAndroidでは、慣性スクロールというものが実装されています。
これは、指を素早く動かして離したときに、スクロールが急に止まらず、慣性が働いているかのように動く機能のことです。
これによって、操作可能範囲が限られたスマホでも、効率的にスクロールできる…らしいです。

で、iOSのSafariでは、この慣性スクロールが停止したときにscrollイベントが1回だけ発火する仕様とのこと。
ちなみに、AndroidはPCと同様にスクロール中は連続的にscrollイベントが発火するそうです。

この解決方法はまだ見つかっていないので、いい案があれば教えていただければと思います。

まとめ

今回は、スマホのウェブページにおけるイベントの発火タイミングについてまとめました。
スマホはOSや機種によって微妙な違いがあって、レイアウト崩れなどこまごまとした問題がいろいろ出てきて大変ですね。

余談ですが、この記事を書いている間、Macがtouchendtouchedに自動スペル修正をしてくれて非常に大変でした。