Beseitigen Sie eine Verzögerung von 300 ms bei Klickereignissen in Mobile Safari

88

Ich habe gelesen, dass Mobile Safari eine Verzögerung von 300 ms für Klickereignisse vom Zeitpunkt des Klickens auf den Link / die Schaltfläche bis zum Zeitpunkt des Auslösens des Ereignisses hat. Der Grund für die Verzögerung besteht darin, abzuwarten, ob der Benutzer einen Doppelklick beabsichtigt. Aus UX-Sicht ist es jedoch häufig unerwünscht, 300 ms zu warten.

Eine Lösung , um diese Verzögerung von 300 ms zu vermeiden, ist die Verwendung der "Tap" -Handhabung von jQuery Mobile. Leider bin ich mit diesem Framework nicht vertraut und möchte kein großes Framework laden, wenn ich nur ein oder zwei Zeilen Code benötigetouchend die richtig angewendet werden.

Wie viele Websites hat meine Website viele Klickereignisse wie das folgende:

$("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
});

und was ich möchte, ist , tun die 300ms loszuwerden Verzögerung auf ALLE diese Klick - Ereignisse einen einzigen Code - Schnipsel wie folgt aus:

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

Ist das eine schlechte / gute Idee?

tim peterson
quelle
@Pointy danke, das könnte einfach funktionieren ...
tim peterson
"... offensichtlich ist das aus UX-Sicht nicht großartig." Ich wäre vorsichtig mit dieser Annahme.
Oliver Moran
1
@OliverMoran, danke für die Korrektur, ich habe gerade diesen Satz bearbeitet, siehe die Frage oben ..
Tim Peterson
1
könnte eine Lösung sein: stackoverflow.com/a/12969739/1491212
Armel Larcier

Antworten:

72

Einige mobile Browser eliminieren jetzt eine Klickverzögerung von 300 ms, wenn Sie das Ansichtsfenster festlegen. Sie müssen keine Problemumgehungen mehr verwenden.

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

Dies wird derzeit von Chrome für Android , Firefox für Android und Safari für iOS unterstützt

Unter iOS Safari ist das Doppeltippen jedoch eine Bildlaufgeste auf nicht zoombaren Seiten. Aus diesem Grund können sie die 300-ms-Verzögerung nicht entfernen . Wenn sie die Verzögerung auf nicht zoombaren Seiten nicht beseitigen können, ist es unwahrscheinlich, dass sie auf zoombaren Seiten entfernt wird.

Windows-Telefone behalten auch die Verzögerung von 300 ms auf nicht zoombaren Seiten bei, haben jedoch keine alternative Geste wie iOS, sodass sie diese Verzögerung wie in Chrome entfernen können.Sie können die Verzögerung unter Windows Phone entfernen, indem Sie:

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

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

UPDATE 2015 Dezember

Bisher hatten WebKit und Safari unter iOS eine Verzögerung von 350 ms, bevor durch einfaches Tippen Links oder Schaltflächen aktiviert wurden, damit Benutzer mit doppeltem Tippen in Seiten hineinzoomen können. Chrome hat dies bereits vor einigen Monaten geändert, indem ein intelligenterer Algorithmus verwendet wurde, um dies zu erkennen, und WebKit wird einen ähnlichen Ansatz verfolgen . Der Artikel gibt einige großartige Einblicke, wie Browser mit Berührungsgesten arbeiten und wie Browser immer noch so viel intelligenter werden können als heute.

UPDATE 2016 März

Unter Safari für iOS wurde die Wartezeit von 350 ms zum Erkennen eines zweiten Tippens entfernt, um eine Antwort mit schnellem Tippen zu erstellen. Dies ist für Seiten aktiviert, die ein Ansichtsfenster mit der Breite = Gerätebreite oder vom Benutzer skalierbar = Nein deklarieren. Autoren können sich auch für das Fast-Tap-Verhalten bestimmter Elemente entscheiden, indem sie das hiertouch-action: manipulation dokumentierte CSS verwenden (scrollen Sie nach unten zur Überschrift 'Styling Fast-Tap-Verhalten') und hier .

NoNameProvided
quelle
Tatsächlich gibt es Berührungsereignisse für WP: stackoverflow.com/questions/13396297/…
Cedric Reichenbach
1
Ja, das wird durch -ms-touch-action gesteuert, wie ich in meinem Beitrag geschrieben habe.
NoNameProvided
1
Unter iOS besteht weiterhin ein Problem, wenn die Anwendung von der Startseite aus ausgeführt wird (eigenständig). Wenn jemand eine anständige Lösung dafür gefunden hat, wäre es sehr willkommen
Miguel Guardo
1
Das Einstellen der Touch-Action-Werte auf Manipulation kommt der gewünschten Leistung am nächsten. Wie @MiguelGuardo bereits sagte, geht der Effekt jedoch verloren, wenn Sie die Webseite in iOS als eigenständige App zu Ihrem Startbildschirm hinzufügen.
T. Steele
Möglicherweise kann jemand UIWebView hacken - stackoverflow.com/questions/55155560/…
Eazy
43

Dieses Plugin -FastClick wurde von der Financial Times entwickelt macht es perfekt für Sie!

Stellen Sie jedoch sicher, dass Sie hinzufügen event.stopPropagation();und / oder event.preventDefault();direkt nach der Klickfunktion, da sie sonst möglicherweise doppelt so ausgeführt wird wie bei mir, dh:

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

});
Jonathan
quelle
3
Dies ist nicht perfekt, wenn Sie jquery mobile verwenden (Version 1.3.2 sowieso), es bricht das Schließen des Panel-Widgets github.com/jquery/jquery-mobile/issues/6440
ryan0
Diese event.stopPropagation () ist genau der Grund, warum ich überhaupt auf diese Seite gekommen bin. Funktioniert perfekt, danke!
Lukas
@Jonathan zaubert fastclicknur auf Touch-Geräten, die ein Verzögerungsproblem haben (andernfalls wird es automatisch umgangen ). Das einfache Hinzufügen von stopPropagation& preventDefaultnach jedem Klickereignis kann jedoch unerwünschte Nebeneffekte auf alle Ereignishandler in allen Browsern haben.
Benutzer
17

Ich weiß, dass dies alt ist, aber können Sie nicht einfach testen, ob "touch" im Browser unterstützt wird? Erstellen Sie dann eine Variable, die entweder "touchend" oder "click" ist, und verwenden Sie diese Variable als Ereignis, das an Ihr Element gebunden wird.

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

In diesem Codebeispiel wird überprüft, ob das Ereignis "touchend" im Browser unterstützt wird. Wenn nicht, verwenden wir das Ereignis "click".

(Bearbeiten: "touchend" in "ontouchend" geändert)

Michael Turnwall
quelle
Danke, ich mag die Einfachheit. Ich würde es lieben, wenn andere sich über mögliche Fallstricke informieren.
Tim Peterson
4
Das Touchend-Ereignis kann das Klick-Ereignis nicht ersetzen, da @Andreas Köberle dies in seiner Antwort erklärt. Wie zum Beispiel, wenn Sie scrollen und Ihr Finger auf einer Schaltfläche stoppt, wird der Link ausgelöst ...
adriendenat
Dies ist eine fantastische, leichte Lösung, ohne dass Sie eine große, fette zusätzliche Bibliothek mit Dingen hinzufügen müssen, um die Verzögerung zu beseitigen. Ich wünschte, ich könnte 5 Mal darüber abstimmen! (Solange Sie sich keine Sorgen um das Scroll-Szenario machen!)
Tonejac
2
Für Computer / Browser mit Touch- und Click-Ereignisunterstützung ist dies eine schlechte Lösung.
Alexander O'Mara
1
Einige Geräte unterstützen sowohl Berührungs- als auch Klickereignisse, und Sie möchten, dass beide in unterschiedlichen Situationen ausgelöst werden. Wir haben Situationen erlebt, in denen einige Fenster oder Android-Tablets mit einer Maus offensichtlich ein Klickereignis auslösen, wenn Sie auf ein Objekt klicken, aber auch Berührungsereignisse, wenn Sie auf tippen. Dies bedeutete, dass Sie beide Ereignisse anhören mussten. Als zusätzlichen Komplikationsfaktor würden einige Geräte beim Tippen ein Klickereignis synthetisieren, sodass das Abhören beider Geräte auf diesen Geräten dazu führen kann, dass Ihr Ereignishandler zweimal ausgelöst wird, sofern Sie nicht vorsichtig sind.
1800 INFORMATION
12

Ich bin auf eine äußerst beliebte Alternative namens Hammer.js gestoßen (Github-Seite) die meiner Meinung nach der beste Ansatz ist.

Hammer.js ist eine umfassendere Touch-Bibliothek (mit vielen Swipe-Befehlen) als Fastclick.js (am besten bewertete Antwort).

Beachten Sie jedoch: Scrollen schnell auf mobilen Geräten die Benutzeroberfläche wirklich einsperren neigt , wenn Sie entweder Hammer.js oder Fastclick.js verwenden. Dies ist ein großes Problem, wenn Ihre Website über einen Newsfeed oder eine Benutzeroberfläche verfügt, über die Benutzer häufig scrollen (wie bei den meisten Web-Apps). Aus diesem Grund verwende ich derzeit keines dieser Plugins.

tim peterson
quelle
2
Benutze keine Hammerjs. Es gibt einige schwerwiegende Probleme, zum Beispiel: github.com/EightMedia/hammer.js/issues/388 github.com/EightMedia/hammer.js/issues/366 Verwenden Sie es zumindest nicht, bis sie behoben sind
Adonis K. Kakoulidis
2

Irgendwie scheint das Deaktivieren des Zooms diese kleine Verzögerung zu deaktivieren. Sinnvoll, da dann kein doppeltes Tippen mehr erforderlich ist.

Wie kann ich das Zoomen auf einer mobilen Webseite "deaktivieren"?

Beachten Sie jedoch die Auswirkungen auf die Benutzerfreundlichkeit. Es kann für Webseiten nützlich sein, die als Apps konzipiert sind, sollte aber meiner Meinung nach nicht für allgemeinere "statische" Seiten verwendet werden. Ich benutze es für ein Haustierprojekt, das eine geringe Latenz benötigt.

Ayke
quelle
1

Leider gibt es keine einfache Möglichkeit, dies zu tun. Wenn Sie also nur verwenden touchstartoder touchendandere Probleme haben, wie z. B. wenn jemand auf eine Schaltfläche klickt, beginnt der Bildlauf. Wir verwenden Zepto für eine Weile, und selbst mit diesem wirklich guten Framework sind im Laufe der Zeit einige Probleme aufgetreten . Viele von ihnen sind geschlossen , aber es scheint kein Feld einfacher Lösung zu sein.

Wir haben diese Lösung, um Klicks auf Links global zu verarbeiten:

   $(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 Köberle
quelle
- @ Andreas, danke, also würden Sie befürworten, die von mir veröffentlichte allgemeine tapLösung nicht zu verwenden und die tapEreignisse Element für Element zu berücksichtigen?
Tim Peterson
Nein, das ist nicht der Punkt. Es geht nicht darum, selbst eine tapLösung zu finden. Ich werde meine Antwort aktualisieren.
Andreas Köberle
- @ Andreas, danke für deine Antwort, viele Klickereignisse sind AJAX, so dass das Standardereignis bereits verhindert wird. Würde es Ihnen etwas ausmachen, Ihre Antwort zu aktualisieren, um auch damit umzugehen? Es scheint, dass meine allgemeine tapLösung in diesem Fall genauso aussehen würde wie Ihre?
Tim Peterson
1

Ich suchte nach einem einfachen Weg ohne JQuery und ohne Fastclick-Bibliothek. Das funktioniert bei mir:

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);          
    }
}
Jarda Pavlíček
quelle
0

Nur um einige zusätzliche Informationen bereitzustellen.

Unter iOS 10 <button> s auf meiner Seite nicht kontinuierlich ausgelöst werden. Es gab immer eine Verzögerung.

Ich habe versucht, schnell zu klicken / Hammer / tapjs / Klick durch Touchstart zu ersetzen, alles ist fehlgeschlagen.

UPDATE: Der Grund scheint zu sein, dass der Knopf zu nahe am Rand ist! Bewegen Sie es in die Nähe des Zentrums und bleiben Sie zurück!

theaws.blog
quelle
0

Sie sollten den passiven Modus explizit deklarieren :

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

    alert('fast touch');

}, { passive : true});
Bruno Andrade
quelle
0

In jQuery können Sie das Ereignis "touchend" binden, indem Sie den Code sofort nach dem Tippen auslösen (wie bei einem Tastendruck auf der Tastatur). Getestet auf aktuellen Chrome- und Firefox-Tablet-Versionen. Vergessen Sie nicht, auch für Ihre Touchscreen-Laptops und Desktop-Geräte zu klicken.

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

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

	// everything else
});

Benjamin
quelle