JavaScript と jQuery を使用してタッチ イベントをキャプチャしようとしています。しかし、Android 2.3.2 の Web ブラウザーで非常に奇妙な動作が見られます。
- 画面全体にオレンジ色の枠線とハイライトが一時的に表示されます。
- 間違ったイベントを送ります。
オレンジ色の境界線は、同じ根本的な問題に関連する症状のように見えるので、あまり心配していません。実際には、ブラウザーが問題を起こしていることを知ることができるので便利です。私が本当に知りたいのは、2回のクイックタップに対して適切なタッチイベントを一貫して取得するにはどうすればよいですか? その問題が解決すると、オレンジ色の枠もなくなると思います。
以下は、私がこれまでに解決したすべての苦痛な詳細です。
これは、問題を示し、受信した各イベントの詳細とタイミングに関する多くの診断情報を表示するページです。青い四角形の内側をタップし、次に黒い四角形の内側をすばやくタップすると、オレンジ色のフラッシュ/悪いイベントが発生します。
私の jQuery コードはかなり標準的です。log
関数の実装は重要ではありません。問題は、ブラウザが呼び出す必要があるときに呼び出さないことです。
el = $('#battle');
el.on('touchstart', function(event) {
log(event);
return event.preventDefault();
});
el.on('touchend', function(event) {
return log(event);
});
el.on('touchcancel', function(event) {
return log(event);
});
el.mousedown(function(event) {
log(event);
return event.preventDefault();
});
return el.mouseup(function(event) {
return log(event);
});
最初に説明した現象の詳細:
オレンジ色の境界線と強調表示:これは、ブラウザーがハイパーリンクをクリックしたときにその周囲に描画するのと同じオレンジ色の境界線と強調表示です。しかし、ページにはハイパーリンクがなく、ブラウザーはこのオレンジ色の境界線を画面全体に描画します。具体的には、<div id="battle">
jQuery 経由でイベントをフックしている外側の周囲に描画します。
間違ったイベント:イベントtouchstart
ハンドラーで を呼び出しevent.preventDefault()
て、ブラウザーにスクロールしないように指示したり、マウス イベントを合成しないように指示したりしていtouchstart
ますtouchend
。そして、私は最初のタップのためにそうします。touchstart
しかし、 /の代わりにtouchend
、2 回目のタップでは、タッチ イベント、合成されたマウス イベント、およびtouchcancel
2 回目のタップの不定期、または最初のタップの繰り返しイベントのすべての組み合わせを取得します。詳細は以下。
この動作も非常に特殊な状況でのみ発生します。
- 最初のタップは短くする必要があります (~200ms 未満)。
- その後、2 回目のタップはすぐに行う必要があります (最初のタップから 450 ミリ秒以内
touchstart
)。 - 2 番目のタップは、最初のタップから少なくとも 150 ピクセル離れている必要があります (最初のタップの座標から対角線に沿って測定
touchstart
)。 - と をフックするコードを削除する
mousedown
とmouseup
、オレンジ色の四角形は表示されなくなります。ただし、タッチ イベントはまだ文字化けすることがあります。
イベントが文字化けしているという意味で、私が見ているのは次のとおりです。「1:」と書くと、それはイベントが最初のタップの座標に対するものであることを意味します。「2:」は 2 番目のタップの座標を意味します。次のパターンのイベントが見られました (パーセンテージは、100 回の試行後に各イベントが発生した回数を示します)。
- (50%) 1:touchstart 1:touchend 1:mousedown 1:mouseup (短い遅延) 2:mousedown 2:mouseup
- (35%) 1:タッチスタート 1:タッチエンド 2:タッチスタート 1:マウスダウン 1:マウスアップ 2:タッチエンド
- (10%) 1:touchstart 1:touchend 2:touchstart 1:mousedown 1:mouseup 2:touchcancel (短い遅延) 2:mousedown 2:mouseup
- (3%) 1:touchstart 1:touchend 2:touchstart 2:touchend (短い遅延) 1:mousedown 1:mouseup
- (2%) 1:touchstart 1:touchend 1:mousedown 1:mouseup (2回目のタップは何もしない)
タップする速さに応じて、いくつかのイベントの組み合わせがより頻繁に発生するように見えますが、パターンを完全に突き止めていません. (2 回のすばやく鮮明なタップは、上記の 2 番目の項目に分類される可能性が高いようですが、鮮明さをあまり重視しない、より迅速な発射アプローチは、最初の項目に分類される可能性が高いようです。同様に、上記の「短い遅延」は、約 150 ミリ秒から約 400 ミリ秒の範囲です。パターン全体のリバース エンジニアリングも行っていません。
mousedown
と をフックしない場合mouseup
、分布はおおよそ次のようになります。
- (40%) 1:タッチスタート 1:タッチエンド 2:タッチスタート 2:タッチキャンセル
- (35%) 1:touchstart 1:touchend 2:touchstart 2:touchend (実際に望ましい動作)
- (25%) 1:touchstart 1:touchend (2回目のタップは何もしない)
したがって、マウス イベントをフックしないと、3 分の 1 の確率で動作します。touchcancel
そして、それがと同じことを意味するふりをしても構わないと思っていればtouchend
、最大 75% の確率でそれを得ることができました。しかし、それはまだかなり厄介です。
私がすでに試した代替案:
- jQuery Mobileとevents
vmousedown
をvmouseup
使用してみましたが、2回目のタップで常にトリガーされるとは限りません。これと同じ根本的なイベントの奇妙さのためだと思います。 - タッチ イベントを完全に忘れて、合成されたマウス イベントのみを使用することもできますが、通常、物理的なタップと合成されたマウス イベントの配信の間に約 0.5 秒の遅延がありますが、タッチ イベントは即時であるため、応答性が高くなります。 . また、スクロールを防止したい - これは全画面表示のゲームのためであり、ユーザーが誤ってアドレスバーをスクロールして戻ってゲームの一部をブロックしてしまうのを防ぎたい -
preventDefault
通常touchstart
はそれを達成します (ただし、時折2回目のタップは、実際には画面をスクロールできますpreventDefault
...このイベント全体の混乱を解決したいもう1つの理由)。 - サードパーティの Web ブラウザ ( Dolphin )を試しましたが、イベントに関して同じ問題があります。したがって、おそらく、基になる WebView がイベントをスクリプトに配信する方法に問題があると思います。
HTML、イベントハンドラー、またはその他のものを変更して、2回連続してすばやくタップした場合のタッチイベントを確実に取得する方法を誰かが提案できますか?