JSでtouchstartとclickイベントを2回発生させないようにしつつ同時に指定する
スマホではタッチイベントを使うということをあまり意識せずに clickイベント ですべて書いてしまっている人も多いと思います。スマホではタッチイベントで反応を速くしたい場合、どのような方法があるのか紹介します。
タッチイベントが使えるか判定
var event = 'ontouchstart' in window ? 'touchstart' : 'click';
$('.button').on(event, function() {
// 何らかの処理
});
今はさすがにこの手法を使っていることはないと思いますが、昔はこのように対応していたこともありました。タッチイベントに対応していれば touchstart
を使い、そうでなければ click
イベントを使うという方法です。
しかし、この手法だとタッチにもクリックにも対応したWindowsタブレットなどのPCだと、 タッチが優先 されてしまいマウス操作ができなくなってしまいます。
preventDefault()する
document.querySelector('.button').addEventListener('touchstart', function(event) {
// touchstar以降のイベントを発生させないように
event.preventDefault();
// 何らかの処理
foo();
});
document.querySelector('.button').addEventListener('click', foo);
touchstart と click イベントそれぞれで foo()
という関数を実行するとします。 touchstart のときに event.preventDefault()
で click イベントを発生させないようにしています。
$('.button').on('touchstart click', function(event) {
// touchstar以降のイベントを発生させないように
event.preventDefault();
// 何らかの処理
foo();
});
jQueryを使うとイベントをまとめて指定できるのでスッキリ書くことができます。
ただし、この方法は Android4.3以下 では正しく動作しないことがあるので注意が必要です。軽く検証したところ、Kindle Fire HDX 4.3 や Nexus 4.2 では clickイベントが無効化されず2回実行されてしまう 現象が起こります。モダンブラウザでは問題がないので、古いバージョンを対応することがないのであれば、この手法はシンプルで使いやすいと思います。
フラグで判定
var flag = false;
document.querySelector('.button').addEventListener('touchstart', function() {
flag = true;
// 何らかの処理
foo();
});
document.querySelector('.button').addEventListener('click', function() {
if (flag) {
flag = false;
} else {
// 何らかの処理
foo();
}
});
touchstart イベントのときに flag
を true
にし、 click イベントを発生させないようにしています。
var flag = false;
$('.button').on('touchstart click', function(event) {
if (event.type === 'touchstart') {
flag = true;
}
if (flag) {
flag = false;
} else {
// 何らかの処理
foo();
}
});
これもjQueryでまとめるとスッキリ書くことができます。
clickイベントだけ定義する
ん? 何言ってるの? touchstart
は? と思うかもしれません。そもそも、このようにタッチイベントが使えるときは touchstart
、そうではないときは click
イベントを使うようにしていたのは clickイベントだと反応が遅い ためでした。具体的には touchend と click イベント間で 300〜350ms 反応が遅延してしまうのです。
<meta name="viewport" content="width=device-width">
しかし、最近のブラウザではこの1行を head
内に記述していれば遅延が起こることはないようです。 この表 が参考になります。空欄のところが 遅延あり の端末を示しています。iOSは iOS9.3 で遅延が解消されたものの、 iOS10 ではまた遅延が復活しているようです。実際に検証してみたところ、確かに遅延はありますが、ほんのわずかでした。
html {
-ms-touch-action: manipulation;
touch-action: manipulation;
}
また、 Windowsタブレット などのその他のブラウザ向けにこの指定もしておくといいでしょう。
実際、ドロワーメニュープラグインの有名どころのソースコードを見てみたところ、click イベントだけでした。例えば、 drawer.js や hiraku.js などがそうです。
それでも古いブラウザまで絶対に対応したい場合は、この記事で紹介した方法か、FastClick を使うといいと思います。
CSS本執筆しました!!!
CSS本出します!1/29発売予定
— たかもそ@CSS本1/29発売!! (@takamosoo) 2018年12月31日
自分がCSS学びたての頃にもっとはやく知りたかったテクニックを載せています。CSSの基礎知識について解説していないので、中級者〜向けとなります。CSS入門書を読んではみたものの、思い通りに作れない人にオススメです。
よろしくお願いします。https://t.co/fkz1dM03Pj pic.twitter.com/suYyaPqwIs