最近、業務でiPad用のウェブサイトを作っているのですが、タッチ時の処理を、clickだと挙動がワンテンポ遅れるということでtouchendを使っているところがあります。ところがありますというのは、touchendだと、うまくいかないところがあったためです。
というわけで、わかった範囲でiOSでのclickとtouchendの挙動をまとめてみます。
clickは反応に少し時間がかかる
最初に書いたように、iOSのclickのイベントはタッチして少し時間がたってから発生します。これは、ダブルタップなどのイベントが発生する可能性を考慮してのことのようです(参考:うのらぼ。 – 【JS】iPhoneでタップの反応が遅いと感じたら)。
その要素上でスクロールすると、clickだと反応しないが、touchendは反応してしまう
ある要素上に指をおいてスクロールすると、そのclickイベントは発動しませんが、touchendイベントは発動するようです。そりゃそうだろ、と思うかもしれませんが、touchendイベントで何か処理をする要素上でスクロールした場合はそのイベントを発動してほしくないといった場合の対処方法はちょっと面倒そうです(touchstartとtouchendの両方でウィンドウ位置を見て変わっていたら発動しない、というようなことをすれば実現できるかもしれません)。
clickはその要素上ではなく、その近辺でのタッチでも発動してしまう
どうやら、clickの判定範囲はiOSで大きめにとられているらしく、例えばclickでイベントが発動する要素のすぐ下の要素はtouchendでイベントが発動する要素。なんてものを作っていると、touchendイベントが起こるほうの上の方をタッチすると、両方のイベントが発動してしまいます。
click,touchendで背景変化
例えば、上記のサンプルページの最初のtouchendと書かれた青い要素の、”touchend”を書かれている部分をタッチすると、タッチした場所の背景が黒くなり、少し遅れて上の”click”と書かれた要素の背景も黒くなってしまいます。
ただ、これを、touchendのイベントを呼んだ時に、『event.preventDefault()』を呼んでイベント遷移を止めることで簡単に回避できました。
touchendした後すぐにclickイベントの要素が同じ位置に置かれると、そのclickイベントが発動する
ちょっと意味がわからないかもしれませんが、例えばある箇所をタップすることで、フィルターをクリックすると閉じるモーダルウィンドウが表示されるような状況があるとすると、touchendするとすぐにその上にフィルターが表示され、つづいてそのフィルターのクリックイベントが発動してモーダルウィンドウが閉じてしまうという状況になってしまいます。これも、『event.preventDefault()』を呼ぶと回避できます。
click,touchendでモーダルウィンドウ表示
なお、フィルターのイベントもclickではなくtouchendとすると、フィルターが閉じたところにclickでイベントが発動する要素があるとそのイベントが発動してしまいます。
touchendでアラートを表示するようなイベントを実行した後、touchendでイベントが実行する要素を触れるだけでまたアラートが表示されてしまう
これも意味がわからないかもしれません。簡潔に伝えたいことを伝えれる人間になりたいものです・・・。これは、バグだと自分は思っているのですが、touchendでアラートを表示するようにし、その要素をタップした後、再びその要素に触れるだけで再度アラートが表示されてしまうのです(触れているだけなので、touchendイベントはまだ起こらないはず)。自分自身ではなく、アラートを表示させた後、他のtouchendイベントを実行する要素にも触れただけでアラートが表示されてしまいます。どうも、touchendとalertが干渉しちゃってるようなのですが、原因はわからず。対処方法としては、setTimeoutで非同期にアラートを表示するようにすると、上記のような問題は起こらなくなります(参考:[iPhone]javascriptのtouchendイベントがおかしい。 WEBアプリケーション研究室 開発ノート)。
click,touchendでアラート表示
ちなみに、なぜか自分の使っているタッチパネル対応のWindows7のChromeで上記を試してみたところ、Chromeが落ちました。まるでブラウザを閉じる処理を実行したかのように普通に。
こうやって見ていくと、だいたいはtouchendでも対処方法はありそうですね。実は今回、ブログに書く上でいろいろ調べて対処方法があると気づいたところもあるので、clickとしていたところをtouchendに変えてみようと思います。
コメント