モバイルSafariでクリックイベントの300ミリ秒の遅延を排除


88

モバイルSafariでは、リンク/ボタンがクリックされてからイベントが発生するまでのクリックイベントで300ミリ秒の遅延があることを読みました。遅延の理由は、ユーザーがダブルクリックするつもりかどうかを確認するために待機することですが、UXの観点からは、300ms待機することは望ましくありません。

この300ミリ秒の遅延を解消する1つの解決策は、jQuery Mobileの「タップ」処理を使用することです。残念ながら、私はこのフレームワークに精通しておらず、必要なものが1行または2行のコードをtouchend適切に適用するだけの場合は、大きなフレームワークをロードしたくありません。

多くのサイトと同様に、私のサイトには次のような多くのクリックイベントがあります。

$("button.submitBtn").on('click', function (e) {   
  $.ajaxSubmit({... //ajax form submisssion
});

$("a.ajax").on('click', function (e) {   
  $.ajax({... //ajax page loading
});

$("button.modal").on('click', function (e) {   
      //show/hide modal dialog
});

そして、私がしたいのは、次のような単一のコードスニペットを使用して、すべてのクリックイベントの300ミリ秒の遅延を取り除くことです。

$("a, button").on('tap', function (e) {
 $(this).trigger('click');
 e.preventDefault();
});

それは悪い/良い考えですか?



@先のとがった感謝、これはうまくいくかもしれません...
ティム・ピーターソン

「...明らかに、これはUXの観点からすばらしくありません。」私はこの仮定に警戒するでしょう。
Oliver Moran 2012

1
@OliverMoranは、補正のためのおかげで、私はちょうど文が..上の質問を参照することを編集した
ティム・ピーターソン

1
解決策かもしれません:stackoverflow.com/a/12969739/1491212
Armel Larcier

回答:


72

現在、一部のモバイルブラウザでは、ビューポートを設定した場合、300 msのクリック遅延が解消されています。回避策を使用する必要はもうありません。

<meta name="viewport" content="width=device-width, user-scalable=no">

現在、Chrome for AndroidFirefox for AndroidSafari for iOSがサポートされています

ただし、iOS Safariでは、ダブルタップはズームできないページでのスクロールジェスチャーです。そのため、300msの遅延を取り除くことはできません。ズームできないページの遅延を削除できない場合、ズーム可能なページの遅延を削除することはほとんどありません。

Windows Phoneもズームできないページで300ミリ秒の遅延を保持しますが、iOSのような代替のジェスチャーがないため、Chromeのようにこの遅延を取り除くことができます。以下を使用して、Windows Phoneの遅延を削除できます。

html {
-ms-touch-action: manipulation;
touch-action: manipulation;
}

出典:http : //updates.html5rocks.com/2013/12/300ms-tap-delay-gone-away

2015年12月更新

これまで、iOSのWebKitとSafariでは、リンクまたはボタンをシングルタップでアクティブにしてからダブルタップでページを拡大できるようになるまでに350ミリ秒の遅延がありました。Chromeは、数か月前に、よりスマートなアルゴリズムを使用してこれを検出し、これを変更しました。 WebKitが同様のアプローチでこれを変更しました。この記事は、ブラウザーがタッチジェスチャーでどのように機能するか、そしてブラウザーが現在よりもはるかにスマートになる方法について、いくつかの素晴らしい洞察を提供します。

2016年3月更新

iOSのSafariでは、2番目のタップを検出するための350ミリ秒の待機時間が削除され、「高速タップ」応答が作成されます。これは、width = device-widthまたはuser-scalable = noのいずれかでビューポートを宣言するページで有効です。著者らはまた、CSSを使用して、特定の要素の高速タップ動作にして選ぶことができますtouch-action: manipulation文書化されているように、ここで ( 'スタイリング高速タップ動作]という見出しの下にスクロール)と、ここで


実際には、WPのためのタッチイベントがありますstackoverflow.com/questions/13396297/...
セドリック・ライヘンバッハ

1
はい、私が投稿で書いたように、-ms-touch-actionによって制御されます。
NoNameProvided 2014年

1
ホームページ(スタンドアロン)からアプリケーションを実行すると、iOSにまだ問題が存在します。誰かが適切な回避策を見つけた場合、それは大歓迎です
Miguel Guardo

1
タッチアクション値を操作に設定することは、望ましいパフォーマンスに最も近くなりますが、@ MiguelGuardoが前述したように、iOSのホーム画面にスタンドアロンアプリとしてWebページを追加すると、効果は失われます。
T.スティール2017

-誰かがのUIWebViewをハックすることができかもしれstackoverflow.com/questions/55155560/...
イージー

43

Financial Timesによって開発されたこのプラグイン-FastClick は、あなたにぴったりです。

ただし、クリック関数の直後に直接追加することを確認してください。追加event.stopPropagation();event.preventDefault();ない場合、2回実行される可能性があります。つまり、

$("#buttonId").on('click',function(event){
    event.stopPropagation(); event.preventDefault();
   //do your magic

});

3
jquery mobile(バージョン1.3.2)を使用している場合、これは完璧ではありません。パネルウィジェットgithub.com/jquery/jquery-mobile/issues/6440の
ryan0

そのevent.stopPropagation()が、まさにこのページに最初にアクセスした理由です。完璧に動作します、ありがとう!
Lukas、

@Jonathan fastclickは、遅延の問題があるタッチデバイスでのみマジックを実行します(それ以外の場合は、自動的にバイパスされます)。ただし、すべてのクリックイベントの後にstopPropagationpreventDefaultを追加するだけでは、すべてのブラウザーのすべてのイベントハンドラーに望ましくない影響を与える可能性があります。
ユーザー

17

私はこれが古いことを知っていますが、ブラウザで「タッチ」がサポートされているかどうかをテストすることはできませんか?次に、「タッチエンド」または「クリック」のいずれかの変数を作成し、その変数を要素にバインドされるイベントとして使用しますか?

var clickOrTouch = (('ontouchend' in window)) ? 'touchend' : 'click';
$('#element').on(clickOrTouch, function() {
    // do something
});

そのため、このコードサンプルは、「touchend」イベントがブラウザーでサポートされているかどうかを確認し、サポートされていない場合は「click」イベントを使用します。

(編集:「touchend」を「ontouchend」に変更)


おかげで、私はこれの単純さが好きです。私は他の人がその可能な落とし穴にチャイムを鳴らすのが大好きです。
ティム・ピーターソン2013

4
@AndreasKöberleが彼の返信で説明しているため、touchendイベントはクリックイベントを置き換えることができません。たとえば、スクロールしてボタンを指で止めると、リンクがトリガーされます...
adriendenat 2013年

これは、遅延を取り除くためだけに、大きな脂肪のライブラリを追加する必要がない、素晴らしい軽量ソリューションです。これに5回賛成票を投じたいと思います!(スクロールのシナリオについて心配していない限り!)
tonejac '17

2
タッチアンドクリックイベントをサポートするコンピューター/ブラウザーの場合、これは不適切なソリューションです。
Alexander O'Mara 14

1
一部のデバイスでは、タッチイベントとクリックイベントの両方がサポートされており、さまざまな状況で両方のイベントを発生させたい場合があります。マウスを搭載した一部のウィンドウまたはAndroidタブレットで、クリックしたときにクリックイベントが発生することは明らかですが、タップするとタッチイベントが発生することもあります。つまり、両方のイベントを聞く必要がありました。追加の複雑な要因として、一部のデバイスはタップしたときにクリックイベントを合成するため、これらのデバイスで両方を聞くと、慎重に行わないと、イベントハンドラーが2回起動される可能性があります。
1800情報

12

私が遭遇してきたHammer.jsと呼ばれる非常に人気の高い代替 (Githubのページ)最善の方法だと思います。

Hammer.jsは、Fastclick.js(最も賛成の回答)よりもフル機能のタッチライブラリ(多くのスワイプコマンドがあります)です。

ただし、モバイルデバイスで高速にスクロールすると、Hammer.jsまたはFastclick.jsのいずれかを使用すると、UIがロックされる傾向があります。これは、サイトにニュースフィードや、ユーザーが頻繁にスクロールするインターフェイス(ほとんどのWebアプリのように見える)がある場合の大きな問題です。このため、現時点ではこれらのプラグインのどちらも使用していません。


2
Hammerjsは使用しないでください。これは、例えば、いくつかの深刻な問題があります。github.com/EightMedia/hammer.js/issues/388 github.com/EightMedia/hammer.js/issues/366は、 それらが固定されるまで、少なくとも、それを使用しないでください
アドニスK.カクーリディス

2

どういうわけか、ズームを無効にすると、この小さな遅延が無効になるようです。ダブルタップはもう必要ないので、理にかなっています。

モバイルWebページでズームを「無効」にするにはどうすればよいですか?

ただし、これがユーザビリティに与える影響に注意してください。アプリとしてデザインされたウェブページには役立つかもしれませんが、より一般的な「静的」ページIMHOには使用しないでください。低レイテンシが必要なペットプロジェクトに使用します。


1

残念ながら、これを行う簡単な方法はありません。したがって、単にを使用するtouchstarttouchend、ボタンをクリックしたときに誰かがスクロールを開始するなど、他の問題が発生します。私たちはしばらくの間zeptoを使用していますが、この非常に優れたフレームワークを使用しても、時間の経過とともに発生したいくつかの問題があります。それらの多くは閉じられていますが、それは単純な解決策の分野ではないようです。

リンクのクリックをグローバルに処理するこのソリューションがあります。

   $(document.body).
    on('tap', 'a',function (e) {
      var href = this.getAttribute('href');
      if (e.defaultPrevented || !href) { return; }
      e.preventDefault();
      location.href= href;
    }).
    on('click', 'a', function (e) {
      e.preventDefault();
    });

-@ Andreas、ありがとうございます。tap私が投稿した一般的なソリューションを使用せずtapに、要素ごとにイベントを因数分解することを推奨しますか。
ティムピーターソン2012

いいえ、それはポイントではありません。重要なのはtap、自分でソリューションを構築しようとすることではありません。回答を更新します。
AndreasKöberle2012

-@ Andreas、回答ありがとうございます。多くのクリックイベントはAJAXであるため、デフォルトのイベントはすでに防止されています。これも処理できるように回答を更新していただけませんか。tapこの場合、私の一般的な解決策はあなたのものと同じように見えるでしょうか?
ティムピーターソン2012

1

私はjqueryとfastclickライブラリなしで簡単な方法を探しました。これは私にとってはうまくいきます:

var keyboard = document.getElementById("keyboard");
var buttons = keyboard.children;
var isTouch = ("ontouchstart" in window);
for (var i=0;i<buttons.length;i++) {
    if ( isTouch ) {
        buttons[i].addEventListener('touchstart', clickHandler, false);         
    } else {
        buttons[i].addEventListener('click', clickHandler, false);          
    }
}

0

追加情報を提供するだけです。

iOS 10では<button>、ページのsを継続的にトリガーできませんでした。常に遅れがありました。

fastclick / Hammer / tapjs / clickをtouchstartに置き換えてみましたが、すべて失敗しました。

更新:その理由は、ボタンが端に近すぎるためです!中央近くに移動して、ラグが消えます!


0

あなたは明示的にパッシブモードを宣言することになっています

window.addEventListener('touchstart', (e) => {

    alert('fast touch');

}, { passive : true});

0

jQueryでは、「touchend」イベントをバインドできます。タップ後すぐに魔女トリガーコード(キーボードのキーダウンのようなもの)です。現在のChromeおよびFirefoxタブレットバージョンでテスト済み。タッチスクリーンのラップトップやデスクトップデバイスの場合は、「クリック」も忘れないでください。

jQuery('.yourElements').bind('click touchend',function(event){

    event.stopPropagation();
    event.preventDefault();

	// everything else
});

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.