Loại bỏ độ trễ 300ms đối với các sự kiện nhấp chuột trong Safari di động


88

Tôi đã đọc rằng Safari di động có độ trễ 300ms đối với các sự kiện nhấp chuột từ khi liên kết / nút được nhấp đến khi sự kiện kích hoạt. Lý do của sự chậm trễ là để chờ xem người dùng có ý định nhấp đúp hay không, nhưng từ góc độ UX, việc chờ đợi 300ms thường là không mong muốn.

Một giải pháp để loại bỏ độ trễ 300ms này là sử dụng xử lý "chạm" jQuery Mobile. Thật không may, tôi không quen thuộc với khuôn khổ này và không muốn tải một số khuôn khổ lớn nếu tất cả những gì tôi cần là một hoặc hai dòng mã áp dụng touchendđúng cách.

Giống như nhiều trang khác, trang của tôi có nhiều sự kiện nhấp chuột như thế này:

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

và những gì tôi muốn làm là loại bỏ độ trễ 300ms đối với TẤT CẢ các sự kiện nhấp chuột đó bằng cách sử dụng một đoạn mã như sau:

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

Đó có phải là một ý tưởng tồi / tốt?



@Pointy cảm ơn, sức mạnh này chỉ làm việc ...
tim Peterson

"... rõ ràng điều này không tuyệt vời từ góc độ UX." Tôi sẽ cảnh giác về giả định này.
Oliver Moran

1
@OliverMoran, cảm ơn bạn đã chỉnh sửa, tôi chỉ sửa câu đó, hãy xem câu hỏi ở trên ..
tim peterson

1
có thể là một giải pháp: stackoverflow.com/a/12969739/1491212
Armel Larcier

Câu trả lời:


72

Giờ đây, một số trình duyệt di động loại bỏ độ trễ nhấp chuột 300 ms nếu bạn đặt chế độ xem. Bạn không cần phải sử dụng các giải pháp thay thế nữa.

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

Điều này hiện được hỗ trợ Chrome dành cho Android , Firefox cho AndroidSafari cho iOS

Tuy nhiên trên iOS Safari , nhấn đúp là một cử chỉ cuộn trên các trang không thể thu phóng. Vì lý do đó, họ không thể loại bỏ độ trễ 300ms . Nếu họ không thể loại bỏ độ trễ trên các trang không thể thu phóng, họ không thể xóa nó trên các trang có thể thu phóng.

Windows Phones cũng giữ lại độ trễ 300ms trên các trang không thể phóng to, nhưng chúng không có cử chỉ thay thế như iOS nên có thể loại bỏ độ trễ này như Chrome có.Bạn có thể loại bỏ độ trễ trên Windows Phone bằng cách sử dụng:

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

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

CẬP NHẬT Tháng 12 năm 2015

Cho đến thời điểm hiện tại, WebKit và Safari trên iOS đã có độ trễ 350ms trước khi chạm một lần kích hoạt các liên kết hoặc nút cho phép mọi người phóng to các trang bằng một lần nhấn. Chrome đã thay đổi điều này vài tháng trước bằng cách sử dụng một thuật toán thông minh hơn để phát hiện điều đó và WebKit sẽ làm theo cách tiếp cận tương tự . Bài viết cung cấp một số thông tin chi tiết tuyệt vời về cách trình duyệt hoạt động với cử chỉ cảm ứng và cách trình duyệt vẫn có thể trở nên thông minh hơn nhiều so với hiện nay.

CẬP NHẬT Tháng 3 năm 2016

Trên Safari dành cho iOS, thời gian chờ 350 ms để phát hiện lần nhấn thứ hai đã bị loại bỏ để tạo phản hồi "nhấn nhanh". Điều này được bật cho các trang khai báo chế độ xem có width = device-width hoặc user-scalable = no. Tác giả cũng có thể chọn tham gia hành vi chạm nhanh trên các phần tử cụ thể bằng cách sử dụng CSS touch-action: manipulationnhư được ghi lại ở đây (cuộn xuống tiêu đề 'Tạo kiểu hành vi chạm nhanh') và tại đây .


Trên thực tế, có những sự kiện liên lạc cho WP: stackoverflow.com/questions/13396297/...
Cedric Reichenbach

1
Có được điều khiển bởi -ms-touch-action như tôi đã viết trong bài đăng của mình.
NoNameProvided

1
Sự cố vẫn tồn tại trên iOS khi chạy ứng dụng từ trang chủ (độc lập). Nếu ai đã tìm thấy một workaround đàng hoàng cho nó, nó sẽ rất hoan nghênh
Miguel Guardo

1
Đặt giá trị thao tác chạm cho thao tác gần nhất với hiệu suất mong muốn, nhưng như @MiguelGuardo đã nêu trước đây, hiệu ứng sẽ bị mất khi bạn thêm trang web vào màn hình chính trong iOS dưới dạng ứng dụng độc lập.
T. Steele

Có thể ai đó có thể hack UIWebView - stackoverflow.com/questions/55155560/…
Eazy

43

Plugin -FastClick được phát triển bởi Financial Times sẽ làm điều đó hoàn hảo cho bạn!

Hãy đảm bảo thêm event.stopPropagation();và / hoặc event.preventDefault();trực tiếp sau hàm nhấp chuột, nếu không nó có thể chạy gấp đôi so với tôi đã làm, tức là:

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

});

3
Điều này không hoàn hảo nếu bạn đang sử dụng jquery mobile (dù sao thì phiên bản 1.3.2), nó phá vỡ việc đóng tiện ích bảng điều khiển github.com/jquery/jquery-mobile/issues/6440
ryan0

event.stopPropagation () đó chính là lý do tại sao tôi đến trang này ngay từ đầu. Hoạt động hoàn hảo, cảm ơn bạn!
Lukas

@Jonathan fastclickthực hiện phép thuật của nó chỉ trên các thiết bị cảm ứng có vấn đề về độ trễ (nếu không, nó sẽ tự động bị bỏ qua ). Tuy nhiên, chỉ cần thêm stopPropagation& preventDefaultsau mỗi sự kiện nhấp chuột có thể có ảnh hưởng không mong muốn đến tất cả các trình xử lý sự kiện trong tất cả các trình duyệt.
người dùng

17

Tôi biết điều này là cũ nhưng bạn không thể chỉ kiểm tra để xem liệu "cảm ứng" có được hỗ trợ trong trình duyệt không? Sau đó, tạo một biến "touchhend" hoặc "click" và sử dụng biến đó làm sự kiện liên kết với phần tử của bạn?

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

Vì vậy, mẫu mã đó kiểm tra xem sự kiện "touchhend" có được hỗ trợ trong trình duyệt hay không và nếu không thì chúng tôi sử dụng sự kiện "click".

(Chỉnh sửa: đã thay đổi "touchhend" thành "ontouchend")


Cảm ơn, tôi thích sự đơn giản của điều này. Tôi rất thích người khác giải thích cho những cạm bẫy có thể xảy ra của nó.
tim peterson

4
Sự kiện touchhend không thể thay thế sự kiện nhấp chuột vì những gì @Andreas Köberle giải thích trong câu trả lời của mình. Chẳng hạn như nếu bạn cuộn và ngón tay của bạn dừng lại trên một nút, nó sẽ kích hoạt liên kết ...
adriendenat

Đây là một giải pháp trọng lượng nhẹ tuyệt vời mà không cần phải bao gồm một thư viện bổ sung chất béo lớn chỉ để loại bỏ sự chậm trễ. Ước gì tôi có thể bỏ phiếu 5 lần cho cái này! (miễn là bạn không lo lắng về kịch bản cuộn!)
tonejac

2
Đối với máy tính / trình duyệt có hỗ trợ sự kiện chạm và nhấp chuột, đây là một giải pháp không tồi.
Alexander O'Mara

1
Một số thiết bị hỗ trợ cả sự kiện chạm và nhấp, và bạn muốn chúng kích hoạt trong các tình huống khác nhau. Chúng tôi đã gặp phải tình huống trong đó một số cửa sổ hoặc máy tính bảng Android có chuột rõ ràng sẽ kích hoạt sự kiện nhấp khi bạn nhấp vào một vật, nhưng nó cũng sẽ kích hoạt sự kiện chạm khi bạn chạm. Điều này có nghĩa là bạn phải lắng nghe cả hai sự kiện. Như một yếu tố phức tạp bổ sung, một số thiết bị sẽ tổng hợp một sự kiện nhấp chuột khi bạn chạm vào, vì vậy việc nghe cả hai sự kiện trên các thiết bị đó có thể dẫn đến việc trình xử lý sự kiện của bạn kích hoạt hai lần, trừ khi bạn cẩn thận.
1800 THÔNG TIN

12

Tôi đã tìm thấy một giải pháp thay thế cực kỳ phổ biến được gọi là Hammer.js (trang Github) mà tôi nghĩ là cách tiếp cận tốt nhất.

Hammer.js là một thư viện cảm ứng đầy đủ tính năng hơn (có nhiều lệnh vuốt) hơn Fastclick.js (câu trả lời được ủng hộ nhiều nhất).

Tuy nhiên, hãy cẩn thận: cuộn nhanh trên thiết bị di động có xu hướng thực sự khóa giao diện người dùng khi bạn sử dụng Hammer.js hoặc Fastclick.js. Đây là một vấn đề lớn nếu trang web của bạn có nguồn cấp tin tức hoặc giao diện nơi người dùng sẽ cuộn nhiều (có vẻ giống như hầu hết các ứng dụng web). Vì lý do này, tôi đang sử dụng cả hai plugin này vào lúc này.


2
Không sử dụng Hammerjs. Nó có một số vấn đề nghiêm trọng, ví dụ: github.com/EightMedia/hammer.js/issues/388 github.com/EightMedia/hammer.js/issues/366 Ít nhất là không sử dụng nó cho đến khi chúng được khắc phục
Adonis K. Kakoulidis

2

Bằng cách nào đó, việc tắt tính năng thu phóng dường như vô hiệu hóa độ trễ nhỏ này. Có lý, vì lúc đó không cần nhấn đúp nữa.

Làm cách nào để "tắt" tính năng thu phóng trên trang web di động?

Nhưng hãy lưu ý về tác động khả năng sử dụng mà điều này sẽ có. Nó có thể hữu ích cho các trang web được thiết kế dưới dạng ứng dụng, nhưng không nên được sử dụng cho các trang IMHO 'tĩnh' có mục đích chung hơn. Tôi sử dụng nó cho một dự án thú cưng cần độ trễ thấp.


1

Thật không may là không có cách dễ dàng để làm điều này. Vì vậy, chỉ sử dụng touchstarthoặc touchendsẽ để lại cho bạn các vấn đề khác như ai đó bắt đầu cuộn khi nhấp vào một nút chẳng hạn. Chúng tôi sử dụng zepto trong một thời gian và ngay cả với framework thực sự tốt này, vẫn có một số vấn đề xuất hiện theo thời gian. Rất nhiều người trong số họ đã đóng cửa , nhưng có vẻ như đây không phải là một lĩnh vực có giải pháp đơn giản.

Chúng tôi có giải pháp này để xử lý toàn cầu các nhấp chuột vào liên kết:

   $(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, cảm ơn vì vậy bạn ủng hộ việc không sử dụng tapgiải pháp chung mà tôi đã đăng và tính toán các tapsự kiện trên cơ sở từng phần tử?
tim peterson

Không, đó không phải là vấn đề. Vấn đề là không nên cố gắng tự xây dựng một tapgiải pháp. Tôi sẽ cập nhật câu trả lời của tôi.
Andreas Köberle

- @ Andreas, cảm ơn câu trả lời của bạn, nhiều sự kiện nhấp chuột là AJAX nên sự kiện mặc định đã bị ngăn chặn. Bạn có phiền cập nhật câu trả lời của mình để xử lý vấn đề này không? Có vẻ như tapgiải pháp chung của tôi sẽ giống như giải pháp của bạn trong trường hợp này?
tim peterson

1

Tôi đã tìm kiếm một cách dễ dàng mà không cần jquery và không có thư viện fastclick. Điều này phù hợp với tôi:

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

Chỉ để cung cấp thêm một số thông tin.

Trên iOS 10, <button> không thể kích hoạt liên tục các s trên trang của tôi. Luôn luôn có một độ trễ.

Tôi đã thử fastclick / Hammer / tapjs / thay thế click bằng touchstart, tất cả đều không thành công.

CẬP NHẬT: nguyên nhân dường như là do nút quá sát mép! di chuyển nó đến gần trung tâm và hết lag!


0

Bạn phải khai báo rõ ràng chế độ thụ động :

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

    alert('fast touch');

}, { passive : true});

0

Trong jQuery, bạn có thể liên kết sự kiện "touchhend", mã kích hoạt phù thủy ngay sau khi chạm (giống như thao tác gõ phím trên bàn phím). Đã thử nghiệm trên các phiên bản máy tính bảng Chrome và Firefox hiện tại. Cũng đừng quên "nhấp", đối với máy tính xách tay màn hình cảm ứng và thiết bị máy tính để bàn của bạn.

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

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

	// everything else
});

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.