ขจัดความล่าช้า 300 มิลลิวินาทีในเหตุการณ์การคลิกใน Safari บนมือถือ


89

ฉันได้อ่านพบว่าSafari บนอุปกรณ์เคลื่อนที่มีความล่าช้า 300 มิลลิวินาทีในเหตุการณ์การคลิกตั้งแต่เวลาที่คลิกลิงก์ / ปุ่มจนถึงเวลาที่เหตุการณ์เริ่ม สาเหตุของความล่าช้าคือการรอเพื่อดูว่าผู้ใช้ตั้งใจจะดับเบิลคลิกหรือไม่ แต่จากมุมมองของ UX การรอ 300ms มักไม่เป็นที่พึงปรารถนา

ทางออกหนึ่งในการขจัดความล่าช้า 300 มิลลิวินาทีนี้คือการใช้การจัดการ "แตะ" ของ jQuery Mobile น่าเสียดายที่ฉันไม่คุ้นเคยกับเฟรมเวิร์กนี้และไม่ต้องการโหลดเฟรมเวิร์กขนาดใหญ่หากสิ่งที่ฉันต้องการคือโค้ดหนึ่งหรือสองบรรทัดที่ใช้อย่าง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
});

และสิ่งที่ฉันต้องการจะทำคือการกำจัด 300ms ล่าช้าในทุกกิจกรรมการคลิกที่ใช้โค้ดเดียวเช่นนี้

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

นั่นเป็นความคิดที่ไม่ดี / ดีหรือไม่?



@Pointy ขอบคุณนี่อาจจะใช้ได้ ...
ทิมปี

"... เห็นได้ชัดว่านี่ไม่ใช่สิ่งที่ยอดเยี่ยมจากมุมมอง UX" ฉันจะระมัดระวังเกี่ยวกับสมมติฐานนี้
Oliver Moran

1
@OliverMoran ขอบคุณสำหรับการแก้ไขฉันเพิ่งแก้ไขประโยคนั้นดูคำถามด้านบน ..
tim peterson

1
อาจเป็นวิธีแก้ปัญหา: stackoverflow.com/a/12969739/1491212
Armel Larcier

คำตอบ:


73

ตอนนี้เบราว์เซอร์บนมือถือบางตัวกำจัดความล่าช้าในการคลิก 300 ms หากคุณตั้งค่าวิวพอร์ต คุณไม่จำเป็นต้องใช้วิธีแก้ปัญหาอีกต่อไป

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

ปัจจุบันรองรับ Chrome สำหรับ Android , Firefox สำหรับ AndroidและSafari สำหรับ iOS

อย่างไรก็ตามใน iOS Safariการแตะสองครั้งเป็นท่าทางการเลื่อนบนหน้าที่ไม่สามารถซูมได้ ด้วยเหตุนี้พวกเขาจึงไม่สามารถลบความล่าช้า 300 มิลลิวินาทีได้ หากพวกเขาไม่สามารถขจัดความล่าช้าในหน้าที่ไม่สามารถซูมได้ก็ไม่น่าจะลบออกในหน้าที่ซูมได้

Windows Phonesยังคงรักษาความล่าช้า 300 มิลลิวินาทีในหน้าที่ไม่สามารถซูมได้ แต่ไม่มีท่าทางสัมผัสอื่นเช่น iOS ดังนั้นจึงเป็นไปได้ที่พวกเขาจะลบความล่าช้านี้ออกไปตามที่ Chrome มีคุณสามารถลบความล่าช้าใน Windows Phone โดยใช้:

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

ที่มา: http://updates.html5rocks.com/2013/12/300ms-tap-delay-gone-away

อัพเดท 2558 ธันวาคม

จนถึงขณะนี้ WebKit และ Safari บน iOS มีความล่าช้า 350 มิลลิวินาทีก่อนที่การแตะเพียงครั้งเดียวจะเปิดใช้งานลิงก์หรือปุ่มต่างๆเพื่อให้ผู้ใช้สามารถซูมเข้าสู่หน้าด้วยการแตะสองครั้ง โครเมี่ยมเปลี่ยนแปลงนี้สองสามเดือนที่ผ่านมาแล้วโดยใช้ขั้นตอนวิธีการที่ชาญฉลาดในการตรวจสอบที่และWebKit จะตามมาด้วยวิธีการที่คล้ายกัน บทความนี้ให้ข้อมูลเชิงลึกที่ดีว่าเบราว์เซอร์ทำงานกับท่าทางสัมผัสอย่างไรและเบราว์เซอร์ยังคงฉลาดกว่าที่เป็นอยู่ในปัจจุบันได้อย่างไร

อัพเดท 2559 มีนาคม

บน Safari สำหรับ iOS เวลารอ 350 มิลลิวินาทีในการตรวจจับการแตะครั้งที่สองได้ถูกลบออกเพื่อสร้างการตอบสนองแบบ "แตะเร็ว" เปิดใช้งานสำหรับเพจที่ประกาศวิวพอร์ตที่มี width = device-width หรือ user-scalable = no ผู้เขียนยังสามารถเลือกในเร็วแตะพฤติกรรมในองค์ประกอบที่เฉพาะเจาะจงโดยใช้แบบ CSS touch-action: manipulationเป็นเอกสารที่นี่ (เลื่อนลงไปที่ 'จัดแต่งทรงผมพฤติกรรมอย่างรวดเร็วแตะ' มุ่งหน้า) และที่นี่


จริงๆแล้วมีเหตุการณ์สัมผัสสำหรับ WP: stackoverflow.com/questions/13396297/…
Cedric Reichenbach

1
ใช่ซึ่งควบคุมโดย -ms-touch-action ตามที่ฉันเขียนไว้ในโพสต์ของฉัน
NoNameProvided

1
ปัญหายังคงมีอยู่บน iOS เมื่อเรียกใช้แอปพลิเคชันจากโฮมเพจ (สแตนด์อโลน) หากใครพบวิธีแก้ปัญหาที่เหมาะสมก็ยินดีเป็นอย่างยิ่ง
Miguel Guardo

1
การตั้งค่าการดำเนินการสัมผัสเพื่อการจัดการนั้นใกล้เคียงกับประสิทธิภาพที่ต้องการมากที่สุด แต่ตามที่ @MiguelGuardo ระบุไว้ก่อนหน้านี้เอฟเฟกต์จะหายไปเมื่อคุณเพิ่มหน้าเว็บในหน้าจอหลักใน iOS เป็นแอปแบบสแตนด์อโลน
T. Steele

อาจมีคนแฮก UIWebView ได้ - stackoverflow.com/questions/55155560/…
Eazy

43

ปลั๊กอิน -FastClick ที่พัฒนาโดย Financial Times นี้เหมาะสำหรับคุณ!

ตรวจสอบให้แน่ใจว่าได้เพิ่มevent.stopPropagation();และ / หรือevent.preventDefault();หลังฟังก์ชั่นคลิกโดยตรงมิฉะนั้นอาจทำงานสองครั้งเหมือนที่ทำกับฉันเช่น:

$("#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

@ โจนาธานfastclickใช้เวทมนตร์เฉพาะกับอุปกรณ์สัมผัสที่มีปัญหาการหน่วงเวลา (มิฉะนั้นจะข้ามโดยอัตโนมัติ ) อย่างไรก็ตามการเพิ่มstopPropagation& preventDefaultหลังทุกเหตุการณ์การคลิกอาจส่งผลกระทบด้านที่ไม่ต้องการกับตัวจัดการเหตุการณ์ทั้งหมดในเบราว์เซอร์ทั้งหมด
ผู้ใช้

17

ฉันรู้ว่านี่เก่า แต่คุณไม่สามารถทดสอบดูว่าเบราว์เซอร์รองรับ "touch" หรือไม่ จากนั้นสร้างตัวแปรที่เป็น "แตะ" หรือ "คลิก" แล้วใช้ตัวแปรนั้นเป็นเหตุการณ์ที่เชื่อมโยงกับองค์ประกอบของคุณ?

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

เพื่อให้ตัวอย่างโค้ดตรวจสอบเพื่อดูว่าเหตุการณ์ "การแตะ" ได้รับการสนับสนุนในเบราว์เซอร์หรือไม่และหากไม่เป็นเช่นนั้นเราจะใช้เหตุการณ์ "คลิก"

(แก้ไข: เปลี่ยน "touchend" เป็น "ontouchend")


ขอบคุณฉันชอบความเรียบง่ายของสิ่งนี้ ฉันชอบให้คนอื่นตีระฆังในข้อผิดพลาดที่เป็นไปได้
ทิมปีเตอร์สัน

4
กิจกรรมการสัมผัสไม่สามารถแทนที่เหตุการณ์การคลิกได้เนื่องจากสิ่งที่ @Andreas Köberleอธิบายไว้ในการตอบกลับของเขา เช่นถ้าคุณเลื่อนและนิ้วของคุณหยุดที่ปุ่มมันจะทริกเกอร์ลิงค์ ...
adriendenat

นี่เป็นโซลูชันน้ำหนักเบาที่ยอดเยี่ยมโดยไม่ต้องรวมไลบรารีของสิ่งต่างๆที่มีไขมันมากเพียงเพื่อกำจัดความล่าช้า หวังว่าฉันจะสามารถโหวตได้ 5 ครั้งในอันนี้! (ตราบเท่าที่คุณไม่กังวลเกี่ยวกับสถานการณ์เลื่อน!)
tonejac

2
สำหรับคอมพิวเตอร์ / เบราว์เซอร์ที่รองรับเหตุการณ์แบบสัมผัสและคลิกนี่เป็นวิธีแก้ปัญหาที่ไม่ดี
Alexander O'Mara

1
อุปกรณ์บางอย่างรองรับทั้งการสัมผัสและการคลิกและคุณต้องการให้ทั้งคู่เริ่มทำงานในสถานการณ์ต่างๆ เราเคยประสบกับสถานการณ์ที่เห็นได้ชัดว่า Windows หรือแท็บเล็ต Android บางรุ่นที่มีเมาส์จะทำให้เกิดเหตุการณ์การคลิกเมื่อคุณคลิกสิ่งใดสิ่งหนึ่ง แต่จะทำให้เหตุการณ์การสัมผัสเกิดขึ้นเมื่อคุณแตะ นั่นหมายความว่าคุณต้องฟังทั้งสองเหตุการณ์ เนื่องจากเป็นปัจจัยที่ซับซ้อนเพิ่มเติมอุปกรณ์บางอย่างอาจสังเคราะห์เหตุการณ์การคลิกเมื่อคุณแตะดังนั้นการฟังทั้งสองบนอุปกรณ์เหล่านั้นอาจส่งผลให้ตัวจัดการเหตุการณ์ของคุณเริ่มทำงานสองครั้งเว้นแต่คุณจะระมัดระวัง
1800 ข้อมูล

12

ฉันเจอทางเลือกยอดนิยมอย่างมากชื่อว่า Hammer.js (หน้า Github)ซึ่งฉันคิดว่าเป็นแนวทางที่ดีที่สุด

Hammer.js เป็นไลบรารีแบบสัมผัสที่มีคุณสมบัติครบถ้วน (มีคำสั่งรูดหลายคำสั่ง) มากกว่า Fastclick.js (คำตอบที่โหวตมากที่สุด)

ระวัง: การเลื่อนอย่างรวดเร็วบนอุปกรณ์มือถือมีแนวโน้มที่จะล็อก UI จริงๆเมื่อคุณใช้ Hammer.js หรือ Fastclick.js นี่เป็นปัญหาสำคัญหากไซต์ของคุณมีตัวดึงข้อมูลข่าวสารหรืออินเทอร์เฟซที่ผู้ใช้จะต้องเลื่อนดูมาก (ดูเหมือนเว็บแอปส่วนใหญ่) ด้วยเหตุนี้ฉันจึงไม่ได้ใช้ปลั๊กอินเหล่านี้ในขณะนี้


2
อย่าใช้ Hammerjs มีปัญหาร้ายแรงบางอย่างเช่นgithub.com/EightMedia/hammer.js/issues/388 github.com/EightMedia/hammer.js/issues/366 อย่างน้อยอย่าใช้จนกว่าจะได้รับการแก้ไข
Adonis K. Kakoulidis

2

อย่างไรก็ตามการปิดใช้งานการซูมดูเหมือนจะปิดใช้งานการหน่วงเวลาเล็กน้อยนี้ สมเหตุสมผลแล้วเพราะไม่จำเป็นต้องแตะสองครั้งอีกต่อไป

ฉันจะ "ปิด" การซูมบนหน้าเว็บบนมือถือได้อย่างไร?

แต่โปรดทราบถึงผลกระทบจากการใช้งานที่จะเกิดขึ้น อาจมีประโยชน์สำหรับหน้าเว็บที่ออกแบบเป็นแอป แต่ไม่ควรใช้สำหรับหน้า 'คงที่' ที่มีวัตถุประสงค์ทั่วไปมากกว่า IMHO ฉันใช้สำหรับโครงการสัตว์เลี้ยงที่ต้องการเวลาแฝงต่ำ


1

น่าเสียดายที่ไม่มีวิธีง่ายๆในการทำเช่นนี้ ดังนั้นเพียงแค่ใช้touchstartหรือtouchendจะทำให้คุณมีปัญหาอื่น ๆ เช่นมีคนเริ่มเลื่อนเมื่อคลิกที่ปุ่มเช่น เราใช้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เหตุการณ์ตามองค์ประกอบทีละองค์ประกอบ?
ทิมปีเตอร์สัน

ไม่นั่นไม่ใช่ประเด็น ประเด็นไม่ได้อยู่ที่การพยายามสร้างtapโซลูชันด้วยตัวเอง ฉันจะอัปเดตคำตอบของฉัน
Andreas Köberle

- @ Andreas ขอบคุณสำหรับคำตอบของคุณเหตุการณ์การคลิกจำนวนมากเป็น AJAX ดังนั้นเหตุการณ์เริ่มต้นจึงถูกป้องกันไว้แล้ว คุณช่วยปรับปรุงคำตอบของคุณเพื่อจัดการเรื่องนี้ด้วยหรือไม่ ดูเหมือนว่าtapโซลูชันทั่วไปของฉันจะดูเหมือนกับของคุณในกรณีนี้?
ทิมปีเตอร์สัน

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>บนเพจของฉันไม่สามารถเปิดใช้งานได้อย่างต่อเนื่อง มักจะมีความล่าช้า

ฉันลอง fastclick / Hammer / tapjs / แทนที่คลิกด้วย touchstart ทั้งหมดล้มเหลว

UPDATE: สาเหตุน่าจะมาจากปุ่มใกล้ขอบเกินไป! ย้ายไปใกล้ศูนย์กลางและความล่าช้าหายไป!


0

คุณควรจะประกาศโหมดพาสซีฟอย่างชัดเจน :

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

    alert('fast touch');

}, { passive : true});

0

ใน jQuery คุณสามารถผูกเหตุการณ์ "สัมผัส" รหัสทริกเกอร์แม่มดได้ทันทีหลังจากแตะ (เปรียบเสมือนการกดแป้นพิมพ์ในแป้นพิมพ์) ทดสอบกับแท็บเล็ต 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.