ボタンをサクサク動かしたい...!
iOS Safariでタップのイベントを取得しようとして、かなりハマりました。
どこで嵌ったかというと、ボタンを連打させたいのに、
onClickやonTapイベントをlistenしていたのでは、あまりに動作が遅い。。。。
タップ後にページ遷移するならいいんですが、
連打なんかで次々処理を進めたい時には、
ちょっと耐えられないレベルです。
原因
コードに無駄があって重いのかと最初は思いましたが、
どうやらそうではなくて、ダブルタップかどうかの判別のために、
あえてタップの認識を遅延させているんですね。
https://developer.apple.com/library/safari/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html
でも、viewportなんかでページを拡大させないようにしているなら、
ダブルタップの認識はむしろ邪魔ですね。。。
対策
では、どうするか。
調べて見ると、
イベントの中でもtouchstart(タップ開始)やtouchend(タップ終了)は、
即、認識できる模様。
そんなわけで、ブラウザのダブルタップはいっそ無視して、
touchstartイベントとtouchendを見て、即時に処理を実行させちゃいます。
コードとしては、下記のような形になります。
$(function() {
var touched = false;
$("#button").bind({
'touchstart mousedown': function(e) { // PCにも対応させるなら、touchstartではなくmousedown
touched = true;
e.preventDefault(); // このイベントに紐つく動作をキャンセル
},
'touchend mouseup': function(e) {
if (touched) {
// なんか処理
}
touched = false;
e.preventDefault();
}
});
});
これだけで、連打でもモタつかないくらい、タップがサクサクになります。
ついでに長押し(ロングタップ)も検知する
touchstartとtouchendのイベントを利用するということは、
touchstartから何秒たったか、確認することができる、ということです。
つまり、長押しも検知できる、ということになります。
そんなわけで、上のコードにさらに手を加えて、長押しにも対応させてみました。
$(function() {
var touched = false;
var touch_time = 0;
$("#button").bind({
'touchstart mousedown': function(e) {
touched = true;
touch_time = 0;
document.interval = setInterval(function(){
touch_time += 100;
if (touch_time == 1000) {
// ロングタップ(タップから約1秒)時の処理
}
}, 100)
e.preventDefault();
},
'touchend mouseup mouseout': function(e) { // マウスが領域外に出たかどうかも拾うと、より自然
if (touched) {
if (touch_time < 1000 ) {
// 短いタップでの処理
}
}
touched = false;
clearInterval(document.interval);
e.preventDefault();
}
});
});
ここから少しいじるだけでも、ほとんどのタップのパターンに対応できるはずです。