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?



@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

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 .


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

});

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)


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.


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.


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, 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);          
    }
}

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!


0

Sie sollten den passiven Modus explizit deklarieren :

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

    alert('fast touch');

}, { passive : true});

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
});

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.