เพิ่มการแตะไปยังเว็บไซต์

หน้าจอสัมผัสใช้งานกับอุปกรณ์ได้มากขึ้นเรื่อยๆ ตั้งแต่โทรศัพท์ไปจนถึงหน้าจอเดสก์ท็อป แอปของคุณควรตอบสนองต่อการแตะในลักษณะที่เข้าใจง่ายและสวยงาม

หน้าจอสัมผัสใช้งานกับอุปกรณ์ได้มากขึ้นเรื่อยๆ ตั้งแต่โทรศัพท์ไปจนถึงหน้าจอเดสก์ท็อป เมื่อผู้ใช้เลือกที่จะโต้ตอบกับ UI ของคุณ แอป ควรตอบสนองต่อการสัมผัสในลักษณะที่เข้าใจง่าย

ตอบสนองต่อสถานะองค์ประกอบ

คุณเคยแตะหรือคลิกองค์ประกอบหนึ่งๆ บนหน้าเว็บแล้วตั้งคำถามว่าจริงๆ แล้วไซต์ตรวจพบหรือไม่

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

องค์ประกอบ DOM สามารถรับค่าสถานะใดก็ได้ต่อไปนี้ ค่าเริ่มต้น โฟกัส การวางเมาส์ และใช้งานอยู่ หากต้องการเปลี่ยน UI สำหรับแต่ละสถานะเหล่านี้ เราจะต้องใช้รูปแบบกับคลาสจำลองต่อไปนี้ :hover, :focus และ :active ดังที่แสดงด้านล่าง

.btn {
  background-color: #4285f4;
}

.btn:hover {
  background-color: #296cdb;
}

.btn:focus {
  background-color: #0f52c1;

  /* The outline parameter suppresses the border
  color / outline when focused */
  outline: 0;
}

.btn:active {
  background-color: #0039a8;
}

ลองใช้

รูปภาพที่แสดงสีต่างๆ
สำหรับสถานะของปุ่ม

สถานะhoverและ/หรือhoverของเบราว์เซอร์ในอุปกรณ์เคลื่อนที่ส่วนใหญ่จะมีผลกับองค์ประกอบหลังจากที่แตะ

ลองพิจารณาให้ดีๆ ว่าสไตล์ไหนที่คุณตั้งค่าและรูปลักษณ์ที่จะปรากฏต่อผู้ใช้เป็นอย่างไร หลังจากที่สัมผัสเสร็จแล้ว

การระงับรูปแบบเบราว์เซอร์เริ่มต้น

เมื่อเพิ่มสไตล์สำหรับรัฐต่างๆ คุณจะเห็นว่าเบราว์เซอร์ส่วนใหญ่ ใช้รูปแบบของตัวเองเพื่อตอบสนองการแตะของผู้ใช้ ซึ่งส่วนใหญ่เป็นเพราะตอนที่เปิดตัวอุปกรณ์เคลื่อนที่เป็นครั้งแรก เว็บไซต์จำนวนหนึ่งไม่มีการจัดรูปแบบสำหรับสถานะ :active ทำให้เบราว์เซอร์จำนวนมาก เพิ่มสีหรือสไตล์ไฮไลต์เข้าไปเพื่อให้ความคิดเห็นแก่ผู้ใช้

เบราว์เซอร์ส่วนใหญ่ใช้คุณสมบัติ CSS outline เพื่อแสดงวงแหวนรอบองค์ประกอบเมื่อมีการโฟกัสองค์ประกอบ คุณจะระงับได้ด้วยเงื่อนไขต่อไปนี้

.btn:focus {
    outline: 0;

    /* Add replacement focus styling here (i.e. border) */
}

Safari และ Chrome เพิ่มสีไฮไลต์การแตะ ซึ่งป้องกันได้ด้วยพร็อพเพอร์ตี้ CSS -webkit-tap-highlight-color ดังนี้

/* Webkit / Chrome Specific CSS to remove tap
highlight color */
.btn {
  -webkit-tap-highlight-color: transparent;
}

ลองใช้

Internet Explorer บน Windows Phone มีลักษณะการทำงานที่คล้ายกัน แต่จะถูกระงับผ่านเมตาแท็ก ดังนี้

<meta name="msapplication-tap-highlight" content="no">

Firefox มีผลข้างเคียง 2 ประการที่ต้องจัดการ

คลาสจำลอง -moz-focus-inner ซึ่งเพิ่มโครงร่างในองค์ประกอบที่สัมผัสได้ คุณจะนำออกได้โดยการตั้งค่า border: 0

หากคุณใช้องค์ประกอบ <button> ใน Firefox ระบบจะนำการไล่ระดับสีไปใช้ ซึ่งนำออกได้ที่การตั้งค่า background-image: none

/* Firefox Specific CSS to remove button
differences and focus ring */
.btn {
  background-image: none;
}

.btn::-moz-focus-inner {
  border: 0;
}

ลองใช้

กำลังปิดใช้การเลือกของผู้ใช้

เมื่อสร้าง UI อาจมีบางสถานการณ์ที่คุณต้องการให้ผู้ใช้โต้ตอบกับองค์ประกอบ แต่คุณต้องการระงับการทำงานเริ่มต้นของการเลือกข้อความเมื่อกดค้างหรือลากเมาส์ไปที่ UI

ซึ่งทำได้โดยใช้พร็อพเพอร์ตี้ CSS ของ user-select แต่โปรดระวังว่าการทำเช่นนี้อาจทำให้ผู้ใช้extremelyมากหากต้องการเลือกข้อความในองค์ประกอบ ดังนั้นโปรดใช้ความระมัดระวังและรอบคอบ

/* Example: Disable selecting text on a paragraph element: */
p.disable-text-selection {
  user-select: none;
}

ใช้ท่าทางสัมผัสที่กำหนดเอง

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

  1. วิธีรองรับทุกเบราว์เซอร์
  2. วิธีรักษาอัตราเฟรมให้สูงอยู่เสมอ

ในบทความนี้ เราจะพูดถึงหัวข้อเหล่านี้ซึ่งครอบคลุม API ที่เราต้องการ เพื่อรองรับการเข้าถึงทุกเบราว์เซอร์ และพูดถึงวิธีที่เราใช้เหตุการณ์เหล่านี้อย่างมีประสิทธิภาพ

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

เราจะดูตัวอย่าง 2 ตัวอย่างในบทความนี้ ซึ่งจะแสดงทั้งการรองรับเบราว์เซอร์ทั้งหมดและวิธีทำให้อัตราเฟรมสูงอยู่เสมอ

ตัวอย่าง GIF ของการแตะบนเอกสาร

ตัวอย่างแรกจะอนุญาตให้ผู้ใช้โต้ตอบกับองค์ประกอบหนึ่งได้ ในกรณีนี้ คุณอาจต้องการให้เหตุการณ์การแตะทั้งหมดกับองค์ประกอบหนึ่งๆ นั้น ตราบใดที่ท่าทางสัมผัสเริ่มต้นจากองค์ประกอบนั้นๆ เอง เช่น การย้ายนิ้วออกจากองค์ประกอบที่ปัดได้จะยังคงควบคุมองค์ประกอบนั้นได้

วิธีนี้เป็นประโยชน์เนื่องจากให้ความยืดหยุ่นอย่างมากสำหรับผู้ใช้ แต่จะบังคับใช้ข้อจํากัดเกี่ยวกับวิธีที่ผู้ใช้โต้ตอบกับ UI ของคุณได้

ตัวอย่าง GIF ของการแตะองค์ประกอบ

อย่างไรก็ตาม หากคุณคาดว่าผู้ใช้จะโต้ตอบกับองค์ประกอบหลายรายการพร้อมกัน (โดยใช้มัลติทัช) คุณควรจำกัดการสัมผัสกับองค์ประกอบที่เจาะจง

วิธีการนี้มีความยืดหยุ่นมากกว่าสำหรับผู้ใช้ แต่ก็ทำให้ตรรกะของ UI ซับซ้อนยิ่งขึ้นและมีความยืดหยุ่นต่อข้อผิดพลาดของผู้ใช้น้อยกว่า

เพิ่ม Listener เหตุการณ์

Internet Explorer และ Edge PointerEvents คือวิธีที่แนะนำสำหรับการใช้ท่าทางสัมผัสที่กำหนดเองใน Chrome (เวอร์ชัน 55 ขึ้นไป)

ในเบราว์เซอร์อื่นๆ คือ TouchEvents และ MouseEvents คือวิธีการที่ถูกต้อง

ฟีเจอร์ที่ยอดเยี่ยมของ PointerEvents คือการผสานรวมอินพุตหลายประเภท เช่น เหตุการณ์เมาส์ เหตุการณ์การแตะ และเหตุการณ์ด้วยปากกา เป็นชุดโค้ดเรียกกลับชุดเดียว เหตุการณ์ที่จะติดตามคือ pointerdown, pointermove, pointerup และ pointercancel

ค่าที่เทียบเท่าในเบราว์เซอร์อื่นๆ คือ touchstart, touchmove, touchend และ touchcancel สำหรับเหตุการณ์การแตะ และหากต้องการใช้ ท่าทางสัมผัสเดียวกันสำหรับอินพุตเมาส์ คุณจะต้องใช้ mousedown, mousemove และ mouseup

หากคุณมีคำถามเกี่ยวกับเหตุการณ์ที่จะใช้ ให้ดูตารางเหตุการณ์การแตะ เมาส์ และตัวชี้

การใช้เหตุการณ์เหล่านี้ต้องมีการเรียกเมธอด addEventListener() ในองค์ประกอบ DOM พร้อมกับชื่อเหตุการณ์ ฟังก์ชันเรียกกลับ และบูลีน บูลีนจะระบุว่าคุณควรจับเหตุการณ์ก่อนหรือหลังองค์ประกอบอื่นๆ ที่มีโอกาสจับและตีความเหตุการณ์ (true หมายถึงคุณต้องการให้เหตุการณ์อยู่ก่อนองค์ประกอบอื่นๆ)

นี่คือตัวอย่างการฟังตอนเริ่มต้นการโต้ตอบ

// Check if pointer events are supported.
if (window.PointerEvent) {
  // Add Pointer Event Listener
  swipeFrontElement.addEventListener('pointerdown', this.handleGestureStart, true);
  swipeFrontElement.addEventListener('pointermove', this.handleGestureMove, true);
  swipeFrontElement.addEventListener('pointerup', this.handleGestureEnd, true);
  swipeFrontElement.addEventListener('pointercancel', this.handleGestureEnd, true);
} else {
  // Add Touch Listener
  swipeFrontElement.addEventListener('touchstart', this.handleGestureStart, true);
  swipeFrontElement.addEventListener('touchmove', this.handleGestureMove, true);
  swipeFrontElement.addEventListener('touchend', this.handleGestureEnd, true);
  swipeFrontElement.addEventListener('touchcancel', this.handleGestureEnd, true);

  // Add Mouse Listener
  swipeFrontElement.addEventListener('mousedown', this.handleGestureStart, true);
}

ลองใช้

จัดการการโต้ตอบองค์ประกอบเดียว

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

TouchEvents จะติดตามท่าทางสัมผัสหลังจากที่เริ่มต้นโดยไม่คำนึงถึงตำแหน่งที่มีการแตะ และ PointerEvents จะติดตามเหตุการณ์ไม่ว่าการแตะจะเกิดขึ้นที่ใดหลังจากที่เราเรียกใช้ setPointerCapture ในองค์ประกอบ DOM

สำหรับเหตุการณ์การเคลื่อนที่ของเมาส์และเหตุการณ์สิ้นสุด เราจะเพิ่ม Listener เหตุการณ์ในวิธีการเริ่มท่าทางสัมผัสและเพิ่ม Listener ลงในเอกสาร ซึ่งหมายความว่าระบบจะติดตามเคอร์เซอร์ได้จนกว่าท่าทางสัมผัสจะเสร็จสมบูรณ์

ขั้นตอนในการใช้งานมีดังนี้

  1. เพิ่ม Listener TouchEvent และ PointerEvent ทั้งหมด สำหรับ MouseEvent ให้เพิ่มเฉพาะเหตุการณ์เริ่มต้น
  2. ภายในโค้ดเรียกกลับด้วยท่าทางสัมผัสเริ่มต้น ให้เชื่อมโยงเหตุการณ์การเลื่อนเมาส์และสิ้นสุดกับเอกสาร วิธีนี้จะทำให้ระบบได้รับเหตุการณ์เมาส์ทั้งหมด ไม่ว่าเหตุการณ์จะเกิดขึ้นในองค์ประกอบเดิมหรือไม่ก็ตาม สำหรับ PointerEvents เราจำเป็นต้องเรียกใช้ setPointerCapture() ในองค์ประกอบเดิมเพื่อรับเหตุการณ์เพิ่มเติมทั้งหมด จากนั้นให้เริ่มท่าทางสัมผัส
  3. จัดการเหตุการณ์การย้าย
  4. เมื่อเหตุการณ์สิ้นสุด ให้นำการเลื่อนเมาส์และ Listener ปลายทางออกจากเอกสาร แล้วสิ้นสุดท่าทางสัมผัส

ด้านล่างนี้เป็นข้อมูลโค้ดเมธอด handleGestureStart() ซึ่งเพิ่มเหตุการณ์การย้ายและสิ้นสุดลงในเอกสาร

// Handle the start of gestures
this.handleGestureStart = function(evt) {
  evt.preventDefault();

  if(evt.touches && evt.touches.length > 1) {
    return;
  }

  // Add the move and end listeners
  if (window.PointerEvent) {
    evt.target.setPointerCapture(evt.pointerId);
  } else {
    // Add Mouse Listeners
    document.addEventListener('mousemove', this.handleGestureMove, true);
    document.addEventListener('mouseup', this.handleGestureEnd, true);
  }

  initialTouchPos = getGesturePointFromEvent(evt);

  swipeFrontElement.style.transition = 'initial';
}.bind(this);

ลองใช้

โค้ดเรียกกลับสิ้นสุดที่เราเพิ่มคือ handleGestureEnd() ซึ่งจะนำ Listener เหตุการณ์การย้ายและสิ้นสุดออกจากเอกสาร และปล่อยการจับภาพตัวชี้เมื่อท่าทางสัมผัสเสร็จสิ้นดังต่อไปนี้

// Handle end gestures
this.handleGestureEnd = function(evt) {
  evt.preventDefault();

  if (evt.touches && evt.touches.length > 0) {
    return;
  }

  rafPending = false;

  // Remove Event Listeners
  if (window.PointerEvent) {
    evt.target.releasePointerCapture(evt.pointerId);
  } else {
    // Remove Mouse Listeners
    document.removeEventListener('mousemove', this.handleGestureMove, true);
    document.removeEventListener('mouseup', this.handleGestureEnd, true);
  }

  updateSwipeRestPosition();

  initialTouchPos = null;
}.bind(this);

ลองใช้

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

แผนภาพนี้แสดงการทำงานของเหตุการณ์การแตะเมื่อเราเพิ่มการย้ายและสิ้นสุดเหตุการณ์ลงในเอกสารเมื่อเริ่มท่าทางสัมผัส

แสดงการเชื่อมโยงเหตุการณ์การแตะกับเอกสารใน &quot;touchstart&quot;

ตอบสนองต่อการแตะได้อย่างมีประสิทธิภาพ

ตอนนี้เรามีเหตุการณ์เริ่มต้นและสิ้นสุดแล้ว เราจึงสามารถตอบสนองต่อเหตุการณ์การสัมผัสได้

สำหรับเหตุการณ์เริ่มต้นและย้าย คุณจะดึงข้อมูล x และ y จากเหตุการณ์ได้อย่างง่ายดาย

ตัวอย่างต่อไปนี้จะตรวจสอบว่าเหตุการณ์มาจาก TouchEvent หรือไม่ โดยตรวจสอบว่ามี targetTouches อยู่หรือไม่ หากเชื่อมต่อ ระบบจะแยก clientX และ clientY ออกจากการแตะครั้งแรก หากเหตุการณ์เป็น PointerEvent หรือ MouseEvent เหตุการณ์จะแยก clientX และ clientY ออกจากเหตุการณ์โดยตรง

function getGesturePointFromEvent(evt) {
    var point = {};

    if (evt.targetTouches) {
      // Prefer Touch Events
      point.x = evt.targetTouches[0].clientX;
      point.y = evt.targetTouches[0].clientY;
    } else {
      // Either Mouse event or Pointer Event
      point.x = evt.clientX;
      point.y = evt.clientY;
    }

    return point;
  }

ลองใช้

TouchEvent มีรายการ 3 รายการที่มีข้อมูลการสัมผัส ดังนี้

  • touches: รายการการแตะปัจจุบันทั้งหมดบนหน้าจอ ไม่ว่าผู้ใช้จะอยู่ที่องค์ประกอบ DOM ใด
  • targetTouches: รายการการแตะที่องค์ประกอบ DOM ที่เชื่อมโยงกับเหตุการณ์ในปัจจุบัน
  • changedTouches: รายการสัมผัสที่มีการเปลี่ยนแปลงซึ่งส่งผลให้เหตุการณ์เริ่มทำงาน

ในกรณีส่วนใหญ่ targetTouches จะให้ทุกสิ่งที่คุณต้องการและจำเป็นต้องใช้ (ดูข้อมูลเพิ่มเติมเกี่ยวกับรายการเหล่านี้ได้ที่รายการการแตะ)

ใช้ requestAnimationFrame

เนื่องจากโค้ดเรียกกลับของเหตุการณ์เริ่มทำงานในเทรดหลัก เราจึงต้องการเรียกใช้โค้ดในการเรียกกลับสำหรับเหตุการณ์ของเราให้น้อยที่สุดเท่าที่จะทำได้ เพื่อรักษาอัตราเฟรมให้สูงและป้องกันความยุ่งยาก

การใช้ requestAnimationFrame() ทำให้เรามีโอกาสอัปเดต UI ก่อนที่เบราว์เซอร์จะวาดเฟรมและช่วยให้เราย้ายการทำงานบางส่วนออกจากโค้ดเรียกกลับของกิจกรรม

หากคุณไม่คุ้นเคยกับ requestAnimationFrame() โปรดดูข้อมูลเพิ่มเติมที่นี่

การใช้งานทั่วไปคือการบันทึกพิกัด x และ y จากเหตุการณ์เริ่มต้นและย้าย แล้วขอเฟรมภาพเคลื่อนไหวภายในโค้ดเรียกกลับของเหตุการณ์การย้าย

ในการสาธิตของเรา เราจัดเก็บตำแหน่งการสัมผัสเริ่มต้นใน handleGestureStart() (มองหา initialTouchPos):

// Handle the start of gestures
this.handleGestureStart = function(evt) {
  evt.preventDefault();

  if (evt.touches && evt.touches.length > 1) {
    return;
  }

  // Add the move and end listeners
  if (window.PointerEvent) {
    evt.target.setPointerCapture(evt.pointerId);
  } else {
    // Add Mouse Listeners
    document.addEventListener('mousemove', this.handleGestureMove, true);
    document.addEventListener('mouseup', this.handleGestureEnd, true);
  }

  initialTouchPos = getGesturePointFromEvent(evt);

  swipeFrontElement.style.transition = 'initial';
}.bind(this);

เมธอด handleGestureMove() จะจัดเก็บตำแหน่งของเหตุการณ์ก่อนที่จะขอเฟรมภาพเคลื่อนไหวหากจำเป็น โดยส่งในฟังก์ชัน onAnimFrame() เป็นโค้ดเรียกกลับ

this.handleGestureMove = function (evt) {
  evt.preventDefault();

  if (!initialTouchPos) {
    return;
  }

  lastTouchPos = getGesturePointFromEvent(evt);

  if (rafPending) {
    return;
  }

  rafPending = true;

  window.requestAnimFrame(onAnimFrame);
}.bind(this);

ค่า onAnimFrame เป็นฟังก์ชันที่เมื่อเรียกใช้แล้วจะเปลี่ยนแปลง UI เพื่อย้ายไปรอบๆ การส่งฟังก์ชันนี้ไปยัง requestAnimationFrame() เราจะบอกเบราว์เซอร์ให้เรียกใช้ก่อนที่เบราว์เซอร์จะอัปเดตหน้าเว็บ (กล่าวคือ สร้างการเปลี่ยนแปลงในหน้าเว็บ)

ในโค้ดเรียกกลับ handleGestureMove() ในระยะแรก เราจะตรวจสอบว่า rafPending เป็นเท็จหรือไม่ ซึ่งระบุว่า requestAnimationFrame() เรียก onAnimFrame() ตั้งแต่เหตุการณ์การย้ายครั้งล่าสุดหรือไม่ ซึ่งหมายความว่าเรามี requestAnimationFrame() เพียงรายการเดียวที่รอเรียกใช้ในแต่ละครั้ง

เมื่อระบบเรียกใช้โค้ดเรียกกลับ onAnimFrame() เราจะตั้งค่าการเปลี่ยนรูปแบบในองค์ประกอบที่ต้องการย้ายก่อนอัปเดต rafPending เป็น false ซึ่งทำให้เหตุการณ์การแตะครั้งถัดไปขอเฟรมภาพเคลื่อนไหวใหม่ได้

function onAnimFrame() {
  if (!rafPending) {
    return;
  }

  var differenceInX = initialTouchPos.x - lastTouchPos.x;
  var newXTransform = (currentXPosition - differenceInX)+'px';
  var transformStyle = 'translateX('+newXTransform+')';

  swipeFrontElement.style.webkitTransform = transformStyle;
  swipeFrontElement.style.MozTransform = transformStyle;
  swipeFrontElement.style.msTransform = transformStyle;
  swipeFrontElement.style.transform = transformStyle;

  rafPending = false;
}

ควบคุมท่าทางสัมผัสโดยใช้การทำงานด้วยการสัมผัส

คุณสมบัติ CSS touch-action ช่วยให้คุณควบคุมลักษณะการทำงานของการแตะที่เป็นค่าเริ่มต้นขององค์ประกอบได้ ในตัวอย่างของเรา เราใช้ touch-action: none เพื่อป้องกันไม่ให้เบราว์เซอร์ดำเนินการใดๆ กับการแตะของผู้ใช้ ซึ่งทำให้เราสามารถดักจับกิจกรรมการแตะทั้งหมดได้

/* Pass all touches to javascript: */
button.custom-touch-logic {
  touch-action: none;
}

การใช้ touch-action: none ค่อนข้างเป็นตัวเลือกที่นิวเคลียร์เพราะจะป้องกันลักษณะการทำงานเริ่มต้นทั้งหมดของเบราว์เซอร์ ในหลายๆ กรณี ตัวเลือกหนึ่งด้านล่างอาจเป็นทางออกที่ดีกว่า

touch-action อนุญาตให้คุณปิดใช้ท่าทางสัมผัสในเบราว์เซอร์ ตัวอย่างเช่น IE10+ รองรับการแตะสองครั้งเพื่อซูมท่าทางสัมผัส การตั้งค่า touch-action เป็น manipulation หมายความว่าคุณป้องกันไม่ให้มีการแตะสองครั้งตามค่าเริ่มต้น

ซึ่งจะช่วยให้คุณใช้ท่าทางสัมผัสการแตะสองครั้งได้ด้วยตนเอง

รายการค่า touch-action ที่ใช้กันโดยทั่วไปมีดังนี้

พารามิเตอร์การทำงานด้วยการแตะ
touch-action: none เบราว์เซอร์จะไม่จัดการการโต้ตอบด้วยการสัมผัส
touch-action: pinch-zoom ปิดใช้การโต้ตอบทั้งหมดของเบราว์เซอร์ เช่น "touch-action: none" จาก "pinch-zoom" ซึ่งเบราว์เซอร์ยังจัดการอยู่
touch-action: pan-y pinch-zoom จัดการการเลื่อนแนวนอนใน JavaScript โดยไม่ปิดใช้การเลื่อนแนวตั้งหรือการซูมด้วยนิ้ว (เช่น ภาพสไลด์)
touch-action: manipulation ปิดใช้ท่าทางสัมผัสการแตะสองครั้งซึ่งเบราว์เซอร์จะหลีกเลี่ยงความล่าช้าของการคลิกได้ ไม่ต้องเลื่อนลงและบีบนิ้วเพื่อซูมไปที่เบราว์เซอร์

การรองรับ IE เวอร์ชันเก่า

หากต้องการรองรับ IE10 คุณต้องจัดการ PointerEvents เวอร์ชันนำหน้าของผู้ให้บริการ

ในการตรวจสอบการรองรับ PointerEvents ที่คุณต้องใช้เป็นประจำ window.PointerEvent แต่ใน IE10 คุณจะต้องค้นหา window.navigator.msPointerEnabled

ชื่อเหตุการณ์ที่คำนำหน้าผู้ให้บริการคือ 'MSPointerDown', 'MSPointerUp' และ 'MSPointerMove'

ตัวอย่างด้านล่างแสดงวิธีตรวจหาการสนับสนุนและเปลี่ยนชื่อเหตุการณ์

var pointerDownName = 'pointerdown';
var pointerUpName = 'pointerup';
var pointerMoveName = 'pointermove';

if (window.navigator.msPointerEnabled) {
  pointerDownName = 'MSPointerDown';
  pointerUpName = 'MSPointerUp';
  pointerMoveName = 'MSPointerMove';
}

// Simple way to check if some form of pointerevents is enabled or not
window.PointerEventsSupport = false;
if (window.PointerEvent || window.navigator.msPointerEnabled) {
  window.PointerEventsSupport = true;
}

ดูข้อมูลเพิ่มเติมได้ในบทความอัปเดตจาก Microsoft นี้

ข้อมูลอ้างอิง

คลาสจำลองสำหรับสถานะการสัมผัส

ระดับ ตัวอย่าง คำอธิบาย
:hover
ปุ่มในสถานะที่กด
ป้อนเมื่อวางเคอร์เซอร์เหนือองค์ประกอบหนึ่งๆ การเปลี่ยนแปลงใน UI เมื่อวางเมาส์เหนือองค์ประกอบนั้นมีประโยชน์ในการกระตุ้นให้ผู้ใช้โต้ตอบกับองค์ประกอบ
:โฟกัส
ปุ่มที่มีสถานะโฟกัส
ป้อนเมื่อผู้ใช้กดแท็บผ่านองค์ประกอบในหน้า สถานะโฟกัสช่วยให้ผู้ใช้ทราบว่ากำลังโต้ตอบกับองค์ประกอบใดอยู่ และช่วยให้ผู้ใช้ไปยังส่วนต่างๆ ของ UI ได้อย่างง่ายดายโดยใช้แป้นพิมพ์
:ใช้งาน
ปุ่มในสถานะที่กด
ป้อนเมื่อมีการเลือกองค์ประกอบ เช่น เมื่อผู้ใช้กำลังคลิกหรือแตะองค์ประกอบ

ดูการอ้างอิงเหตุการณ์การแตะที่สมบูรณ์ได้ที่ W3C Touch Event

เหตุการณ์การแตะ เมาส์ และตัวชี้

เหตุการณ์ต่อไปนี้คือองค์ประกอบพื้นฐานในการเพิ่มท่าทางสัมผัสใหม่ลงในแอปพลิเคชันของคุณ

การแตะ เมาส์ เหตุการณ์ตัวชี้
touchstart, mousedown, pointerdown ลักษณะนี้เรียกว่าเมื่อนิ้วแตะองค์ประกอบเป็นครั้งแรกหรือเมื่อผู้ใช้คลิกเมาส์
touchmove, mousemove, pointermove ซึ่งจะเรียกเมื่อผู้ใช้เลื่อนนิ้วผ่านหน้าจอหรือลากเมาส์
touchend, mouseup, pointerup ซึ่งจะเรียกเมื่อผู้ใช้ยกนิ้วออกจากหน้าจอหรือปล่อยเมาส์
touchcancel pointercancel ระบบจะเรียกวิธีนี้เมื่อเบราว์เซอร์ยกเลิกท่าทางแตะสัมผัส เช่น ผู้ใช้แตะเว็บแอปแล้วเปลี่ยนแท็บ

รายการสัมผัส

กิจกรรมการสัมผัสแต่ละกิจกรรมจะมีแอตทริบิวต์รายการ 3 รายการ ดังนี้

แอตทริบิวต์เหตุการณ์การสัมผัส
touches รายการการแตะในปัจจุบันทั้งหมดบนหน้าจอ ไม่ว่าจะแตะองค์ประกอบใดก็ตาม
targetTouches รายการการติดต่อที่เริ่มต้นในองค์ประกอบซึ่งเป็นเป้าหมายของเหตุการณ์ปัจจุบัน ตัวอย่างเช่น หากเชื่อมโยงกับ <button> คุณจะแตะที่ปุ่มดังกล่าวได้ในขณะนี้เท่านั้น หากคุณเชื่อมโยงกับเอกสาร คุณจะได้รับการแตะทั้งหมดที่มีอยู่ในเอกสารในขณะนี้
changedTouches รายการการแตะที่มีการเปลี่ยนแปลงซึ่งส่งผลให้เหตุการณ์เริ่มทำงาน:
  • สำหรับเหตุการณ์ touchstart -- รายการทัชพอยต์ที่เพิ่งเริ่มใช้งานกับเหตุการณ์ปัจจุบัน
  • สำหรับเหตุการณ์ touchmove -- รายการทัชพอยต์ที่มีการย้ายนับตั้งแต่เหตุการณ์ล่าสุด
  • สำหรับเหตุการณ์ touchend และ touchcancel รายการทัชพอยต์ที่เพิ่งนำออกจากแพลตฟอร์ม

การเปิดใช้การสนับสนุนสถานะที่ใช้งานอยู่ใน iOS

ขออภัย Safari ใน iOS ไม่ได้ใช้สถานะใช้งานอยู่โดยค่าเริ่มต้น เพื่อให้ทำงานได้ คุณต้องเพิ่ม Listener เหตุการณ์ touchstart ลงในเนื้อหาเอกสารหรือลงในองค์ประกอบแต่ละรายการ

โดยควรทำหลังการทดสอบ User Agent เพื่อให้ทำงานในอุปกรณ์ iOS เท่านั้น

การเพิ่มการเริ่มต้นสัมผัสในเนื้อความมีประโยชน์จากการใช้กับองค์ประกอบทั้งหมดใน DOM แต่วิธีนี้อาจมีปัญหาด้านประสิทธิภาพเมื่อเลื่อนหน้าเว็บ

window.onload = function() {
  if (/iP(hone|ad)/.test(window.navigator.userAgent)) {
    document.body.addEventListener('touchstart', function() {}, false);
  }
};

อีกทางเลือกหนึ่งคือการเพิ่ม Listener การเริ่มการแตะลงในองค์ประกอบที่โต้ตอบได้ทั้งหมดในหน้าเว็บ ซึ่งจะช่วยลดข้อกังวลเรื่องประสิทธิภาพบางส่วน

window.onload = function() {
  if (/iP(hone|ad)/.test(window.navigator.userAgent)) {
    var elements = document.querySelectorAll('button');
    var emptyFunction = function() {};

    for (var i = 0; i < elements.length; i++) {
        elements[i].addEventListener('touchstart', emptyFunction, false);
    }
  }
};