読者です 読者をやめる 読者になる 読者になる

モロ屋

アキバではたらくWebエンジニア。JavaScript / AWS / Mac

スマホWebアプリ作るなら'click'より'tap'使おうよ!

技術系の小ネタ

録りためていたアニメを消化するだけのちっぽけなGWでした… もろやです。

スマホ向けのWebサイトやアプリを開発するときに、jQueryを使って以下のようにイベントを設定することはよくあると思います。

$('.button').on('click', function(){
    alert('button!');
});

しかし、iPhone/Androidなどの一般的なモバイル向けブラウザでは、実際にクリックイベントが発生するまで300msほどの待機時間が発生します。 (touchendイベントが発生してから300ms後にclickイベントが発生する)

そのため、ユーザー視点ではタップするたびに300ms待たされる事になり「Webアプリやっぱなんかもっさりしてるよね」という感覚に繋がっていきます。

そこで、jQuery mobileのtapイベントを使ってその辺を全部解決しちゃおうぜ〜? という話です。

使い方

jQuery mobileは結構巨大なフレームワークになっていて、イベントの処理のためだけに全部をロードするのは重いし不都合もあるので、モバイルイベント処理の部分のみを抜き出したものを作成しました。

jQuery mobile 1.3.1からモバイルイベント部分のみを取り出したもの - gist

これをjQueryプラグインとして読み込み、先ほどのコードをこのように書き換えます。

$('.button').on('tap', function(){
    alert('button!');
    return false;
});

デモ

PCブラウザでは違いが分かりません。

http://jsrun.it/moroya/gqFr にスマホからアクセスするか、以下のQRコードから開いてボックスをタップすると、反応にかなりの差が感じられるのがわかると思います。

image

なぜreturn falseするのか

on('click') から on('tap') に変えるだけじゃダメなの? ということなんですが、それでも動きますが場合によっては不具合が発生します。

この手の処理はtouchstart, touchmove, touchendイベントを検出してtapイベントを発生させています。

そしてclickイベントの代わりにtapが発生するようなイメージになっているのですが、かといってclickイベントが発生しないわけではなく300ms後にタップした座標でclickイベントは当然発生します。

例えばダイアログボックスを画面いっぱいにオーバーレイ表示していて、閉じるボタンをtapイベントで閉じたとします。すると、300ms後に閉じるボタンのあった場所でclickイベントが発生します。

もしダイアログの下にリンクなどがあった場合、ダイアログを閉じただけなのに300ms後にやってきたclickイベントでリンクが押下されたこととなりページが移動してしまいます。

http://jsrun.it/moroya/2uyX に、return falseがある場合とない場合のデモを用意してみました。

image

画面をclickするとアラートが出るようになっており、tap1の方は問題なく動作しますが、tap2の方はボックスしかタップしていないのに画面がclickされたことになりアラートが出ます。

jQuery mobileでは、tapイベントでreturn falseされたときは、次に発生してしまうclickイベントを捕捉し、動作をキャンセルするという処理が自動で実行されます。

そのため、ボックスの下にリンクや要素があってもclickが伝わらないようになっているんですね。超便利。

他にもネット上で、tapイベントを発生させるコードやライブラリがあるのを見ましたが、この「300ms後に発生する正規のclickイベントをキャンセルする処理」というのが入っていませんので使いづらいと思います。

ということで

スマホ向けのWebアプリ作るときは、clickじゃなくてtap使おうぜ!