Hilangkan penundaan 300ms pada peristiwa klik di Safari seluler

89

Saya telah membaca bahwa Safari seluler memiliki penundaan 300ms pada peristiwa klik sejak tautan / tombol diklik hingga saat peristiwa tersebut diaktifkan. Alasan penundaan adalah menunggu untuk melihat apakah pengguna bermaksud untuk melakukan klik dua kali, tetapi dari perspektif UX menunggu 300ms seringkali tidak diinginkan.

Salah satu solusi untuk menghilangkan penundaan 300ms ini adalah dengan menggunakan penanganan "tap" jQuery Mobile. Sayangnya saya tidak terbiasa dengan kerangka kerja ini dan tidak ingin memuat kerangka kerja besar jika yang saya butuhkan hanyalah satu atau dua baris kode yang diterapkan touchenddengan cara yang benar.

Seperti banyak situs, situs saya memiliki banyak peristiwa klik seperti ini:

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

dan yang ingin saya lakukan adalah menghilangkan penundaan 300 md pada SEMUA peristiwa klik tersebut menggunakan satu cuplikan kode seperti ini:

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

Apakah itu ide yang buruk / bagus?

tim peterson
sumber
@ Terima kasih, ini mungkin berhasil ...
tim peterson
"... jelas ini tidak bagus dari perspektif UX." Saya akan waspada dengan asumsi ini.
Oliver Moran
1
@OliverMoran, terima kasih atas koreksinya, saya baru saja mengedit kalimat itu, lihat pertanyaan di atas ..
tim peterson
1
mungkin solusinya: stackoverflow.com/a/12969739/1491212
Armel Larcier

Jawaban:

73

Sekarang beberapa browser seluler menghilangkan penundaan klik 300 ms jika Anda menyetel area pandang. Anda tidak perlu menggunakan solusi lagi.

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

Ini saat ini didukung Chrome untuk Android , Firefox untuk Android dan Safari untuk iOS

Namun di Safari iOS , ketuk dua kali adalah gerakan gulir pada halaman yang tidak dapat diperbesar. Untuk alasan itu mereka tidak dapat menghapus penundaan 300 milidetik . Jika mereka tidak dapat menghapus penundaan pada halaman yang tidak dapat diperbesar, kemungkinan besar mereka tidak akan menghapusnya pada halaman yang dapat diperbesar.

Ponsel Windows juga mempertahankan penundaan 300 md pada halaman yang tidak dapat diperbesar, tetapi mereka tidak memiliki gerakan alternatif seperti iOS sehingga mungkin bagi mereka untuk menghapus penundaan ini seperti yang dimiliki Chrome.Anda dapat menghapus penundaan di Windows Phone menggunakan:

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

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

UPDATE 2015 Desember

Hingga saat ini, WebKit dan Safari di iOS mengalami penundaan 350 ms sebelum satu ketukan mengaktifkan tautan atau tombol untuk memungkinkan orang memperbesar halaman dengan dua ketukan. Chrome mengubah ini beberapa bulan yang lalu dengan menggunakan algoritma yang lebih cerdas untuk mendeteksinya dan WebKit akan mengikuti dengan pendekatan serupa . Artikel ini memberikan beberapa wawasan bagus tentang cara kerja browser dengan gerakan sentuh dan bagaimana browser masih bisa menjadi jauh lebih pintar daripada yang ada saat ini.

UPDATE 2016 Maret

Di Safari untuk iOS, waktu tunggu 350 md untuk mendeteksi ketukan kedua telah dihapus untuk membuat respons "ketukan cepat". Ini diaktifkan untuk halaman yang mendeklarasikan viewport dengan width = device-width atau user-scalable = no. Penulis juga dapat memilih perilaku tap cepat pada elemen tertentu dengan menggunakan CSS touch-action: manipulationseperti yang didokumentasikan di sini (gulir ke bawah ke judul 'Styling Fast-Tap Behavior') dan di sini .

NoNameProvided
sumber
Sebenarnya, ada acara sentuh untuk WP: stackoverflow.com/questions/13396297/…
Cedric Reichenbach
1
Ya yang dikendalikan oleh -ms-touch-action seperti yang saya tulis di posting saya.
NoNameDiberikan
1
Masalah masih ada di iOS saat menjalankan aplikasi dari halaman beranda (mandiri). Jika ada yang menemukan solusi yang layak untuk itu, itu akan sangat disambut
Miguel Guardo
1
Menyetel nilai tindakan sentuh ke manipulasi paling mendekati kinerja yang diinginkan, tetapi seperti yang dikatakan @MiguelGuardo sebelumnya, efeknya hilang setelah Anda menambahkan halaman web ke layar beranda di iOS sebagai aplikasi mandiri.
T. Steele
Mungkin seseorang dapat meretas UIWebView - stackoverflow.com/questions/55155560/…
Eazy
43

Plugin -FastClick yang dikembangkan oleh Financial Times ini melakukannya dengan sempurna untuk Anda!

Pastikan untuk menambahkan event.stopPropagation();dan / atau event.preventDefault();langsung setelah fungsi klik, jika tidak maka akan berjalan dua kali seperti yang saya lakukan, yaitu:

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

});
Jonathan
sumber
3
Ini tidak sempurna jika Anda menggunakan jquery mobile (tetap saja versi 1.3.2), ini merusak penutupan widget panel github.com/jquery/jquery-mobile/issues/6440
ryan0
event.stopPropagation () itu persisnya alasan saya datang ke halaman ini sejak awal. Bekerja dengan sempurna, terima kasih!
Lukas
@Jonathan fastclickmelakukan keajaibannya hanya pada perangkat sentuh yang memiliki masalah penundaan (jika tidak maka secara otomatis dilewati ). Namun, hanya menambahkan stopPropagation& preventDefaultsetelah setiap peristiwa klik mungkin memiliki pengaruh samping yang tidak diinginkan pada semua penangan peristiwa di semua browser.
pengguna
17

saya tahu ini sudah tua tetapi tidak bisakah Anda hanya menguji untuk melihat apakah "sentuhan" didukung di browser? Lalu buat variabel baik itu "touchend" atau "klik" dan gunakan variabel itu sebagai peristiwa yang terikat ke elemen Anda?

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

Jadi contoh kode tersebut memeriksa untuk melihat apakah acara "touchend" didukung di browser dan jika tidak, maka kami menggunakan acara "klik".

(Edit: mengubah "touchend" menjadi "ontouchend")

Michael Turnwall
sumber
Terima kasih, saya suka kesederhanaannya. Saya ingin orang lain menanggapi kemungkinan jebakannya.
tim peterson
4
acara touchend tidak dapat menggantikan acara klik karena apa yang dijelaskan @Andreas Köberle dalam balasannya. Seperti misalnya jika Anda menggulir dan jari Anda berhenti pada sebuah tombol, itu akan memicu tautan ...
adriendenat
Ini adalah solusi ringan yang mengagumkan tanpa harus menyertakan pustaka tambahan yang besar dan gemuk hanya untuk menghilangkan penundaan. Berharap saya bisa memberikan suara 5 kali untuk yang satu ini! (selama Anda tidak khawatir tentang skenario gulir!)
tonejac
2
Untuk komputer / browser dengan dukungan acara sentuh dan klik, ini adalah solusi yang buruk.
Alexander O'Mara
1
Beberapa perangkat mendukung peristiwa sentuh dan klik, dan Anda ingin keduanya diaktifkan dalam situasi yang berbeda. Kami pernah mengalami situasi di mana beberapa jendela atau tablet Android yang memiliki mouse jelas akan mengaktifkan peristiwa klik saat Anda mengklik sesuatu, tetapi peristiwa sentuh juga akan mengaktifkan saat Anda mengetuk. Ini berarti Anda harus mendengarkan kedua acara tersebut. Sebagai faktor rumit tambahan, beberapa perangkat akan mensintesis peristiwa klik saat Anda mengetuk, jadi mendengarkan keduanya di perangkat tersebut dapat mengakibatkan penangan peristiwa Anda diaktifkan dua kali, kecuali Anda berhati-hati.
1800 INFORMASI
12

Saya telah menemukan alternatif yang sangat populer yang disebut Hammer.js (halaman Github) yang menurut saya merupakan pendekatan terbaik.

Hammer.js adalah pustaka sentuh berfitur lengkap (memiliki banyak perintah gesek) daripada Fastclick.js (jawaban dengan suara terbanyak).

Berhati-hatilah: menggulir cepat di perangkat seluler cenderung benar-benar mengunci UI saat Anda menggunakan Hammer.js atau Fastclick.js. Ini adalah masalah besar jika situs Anda memiliki umpan berita atau antarmuka tempat pengguna akan sering menggulir (akan terlihat seperti kebanyakan aplikasi web). Untuk alasan ini, saya tidak menggunakan plugin ini saat ini.

tim peterson
sumber
2
Jangan gunakan Hammerjs. Ini memiliki beberapa masalah serius, misalnya: github.com/EightMedia/hammer.js/issues/388 github.com/EightMedia/hammer.js/issues/366 Setidaknya jangan gunakan sampai diperbaiki
Adonis K. Kakoulidis
2

Entah bagaimana, menonaktifkan zoom tampaknya menonaktifkan penundaan kecil ini. Masuk akal, karena ketuk dua kali tidak diperlukan lagi.

Bagaimana cara "menonaktifkan" zoom pada halaman web seluler?

Namun harap perhatikan dampak kegunaan yang akan ditimbulkan. Ini mungkin berguna untuk halaman web yang dirancang sebagai aplikasi, tetapi tidak boleh digunakan untuk halaman 'statis' tujuan yang lebih umum IMHO. Saya menggunakannya untuk proyek hewan peliharaan yang membutuhkan latensi rendah.

ayke
sumber
1

Sayangnya tidak ada cara mudah untuk melakukan ini. Jadi hanya menggunakan touchstartatau touchendakan meninggalkan Anda dengan masalah lain seperti seseorang mulai menggulir ketika mengklik tombol misalnya. Kami menggunakan zepto untuk sementara waktu, dan bahkan dengan kerangka kerja yang sangat bagus ini ada beberapa masalah yang muncul seiring waktu. Banyak dari mereka tertutup , tetapi tampaknya bukan bidang solusi sederhana.

Kami memiliki solusi ini untuk menangani klik pada tautan secara global:

   $(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
sumber
- @ Andreas, terima kasih jadi Anda akan menganjurkan untuk tidak menggunakan tapsolusi umum yang saya posting dan memfaktorkan tapkejadian berdasarkan elemen-demi-elemen?
tim peterson
Tidak, bukan itu intinya. Intinya bukanlah mencoba membangun tapsolusi sendiri. Saya akan memperbarui jawaban saya.
Andreas Köberle
- @ Andreas, terima kasih atas jawaban Anda, banyak peristiwa klik adalah AJAX sehingga acara default sudah dicegah. Maukah Anda memperbarui jawaban Anda untuk menangani ini juga? Tampaknya tapsolusi umum saya akan terlihat sama dengan solusi Anda dalam kasus ini?
tim peterson
1

Saya mencari cara mudah tanpa jquery dan tanpa fastclick library. Ini bekerja untuk saya:

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
sumber
0

Hanya untuk memberikan beberapa informasi tambahan.

Di iOS 10, <button> s di halaman saya tidak dapat dipicu terus menerus. Selalu ada jeda.

Saya mencoba fastclick / Hammer / tapjs / replacing click dengan touchstart, semuanya gagal.

UPDATE: alasannya sepertinya tombol tersebut terlalu dekat dengan tepi! pindahkan ke dekat pusat dan lag hilang!

theaws.blog
sumber
0

Anda seharusnya secara eksplisit menyatakan mode pasif :

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

    alert('fast touch');

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

Di jQuery Anda dapat mengikat acara "touchend", kode pemicu penyihir segera setelah ketuk (seperti keydown di keyboard). Diuji pada versi tablet Chrome dan Firefox saat ini. Jangan lupa juga "klik", untuk laptop layar sentuh dan perangkat desktop Anda.

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

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

	// everything else
});

Benjamin
sumber