Thêm điểm nhấn vào trang web của bạn

Màn hình cảm ứng có trên ngày càng nhiều thiết bị, từ điện thoại cho đến màn hình máy tính. Ứng dụng của bạn phải phản hồi lại thao tác chạm của người dùng theo cách trực quan và thú vị.

Màn hình cảm ứng có trên ngày càng nhiều thiết bị, từ điện thoại cho đến màn hình máy tính. Khi người dùng chọn tương tác với giao diện người dùng, ứng dụng của bạn phải phản hồi với thao tác chạm của họ theo cách trực quan.

Phản hồi trạng thái của thành phần

Bạn đã bao giờ chạm hoặc nhấp vào một phần tử trên trang web và đặt câu hỏi liệu trang web đó có thực sự phát hiện thấy phần tử đó hay không?

Chỉ cần thay đổi màu của một phần tử khi người dùng chạm hoặc tương tác với các phần trên giao diện người dùng của bạn, bạn sẽ cảm thấy yên tâm rằng trang web của bạn đang hoạt động. Điều này không chỉ giúp giảm sự thất vọng mà còn mang lại cảm giác phản hồi nhanh gọn.

Các phần tử DOM có thể kế thừa bất kỳ trạng thái nào sau đây: mặc định, tâm điểm, di chuột và đang hoạt động. Để thay đổi giao diện người dùng cho từng trạng thái trong số này, chúng ta cần áp dụng kiểu cho các lớp giả sau đây :hover, :focus:active như thể hiện dưới đây:

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

Thử nào

Hình ảnh minh hoạ các màu khác nhau cho trạng thái nút

Trên hầu hết các trình duyệt dành cho thiết bị di động, các trạng thái hover và/hoặc hover sẽ áp dụng cho một phần tử sau khi bạn nhấn vào phần tử đó.

Hãy cân nhắc kỹ những kiểu bạn đã đặt và giao diện mà người dùng sẽ thấy sau khi họ hoàn tất thao tác chạm.

Chặn các kiểu trình duyệt mặc định

Sau khi thêm kiểu cho các trạng thái khác nhau, bạn sẽ nhận thấy hầu hết các trình duyệt đều triển khai kiểu riêng để phản hồi thao tác chạm của người dùng. Nguyên nhân chủ yếu là do khi thiết bị di động ra mắt lần đầu tiên, một số trang web không tạo kiểu cho trạng thái :active. Do đó, nhiều trình duyệt đã thêm kiểu hoặc màu đánh dấu bổ sung để cung cấp ý kiến phản hồi cho người dùng.

Hầu hết các trình duyệt đều sử dụng thuộc tính CSS outline để hiển thị vòng tròn xung quanh một phần tử khi một phần tử được lấy làm tâm điểm. Bạn có thể chặn bằng:

.btn:focus {
    outline: 0;

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

Safari và Chrome thêm một màu đánh dấu thao tác nhấn mà bạn có thể ngăn chặn bằng thuộc tính CSS -webkit-tap-highlight-color:

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

Thử nào

Internet Explorer trên Windows Phone có hành vi tương tự, nhưng bị chặn qua thẻ meta:

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

Firefox có hai hiệu ứng phụ cần xử lý.

Lớp giả -moz-focus-inner thêm đường viền trên các phần tử có thể chạm vào, bạn có thể xoá bằng cách đặt border: 0.

Nếu đang sử dụng phần tử <button> trên Firefox, bạn sẽ được áp dụng một hiệu ứng chuyển màu (gradient) mà bạn có thể xoá bằng cách đặt background-image: none.

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

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

Thử nào

Tắt tính năng chọn người dùng

Khi tạo giao diện người dùng, có thể có những trường hợp bạn muốn người dùng tương tác với các thành phần nhưng lại muốn ngăn chặn hành vi mặc định là chọn văn bản khi nhấn và giữ hoặc kéo chuột qua giao diện người dùng.

Bạn có thể thực hiện việc này với thuộc tính CSS user-select, nhưng xin lưu ý rằng việc này đối với nội dung có thể extremely gây khó chịu cho người dùng nếu họ muốn chọn văn bản trong phần tử. Vì vậy, hãy đảm bảo bạn sử dụng mã này một cách thận trọng và thận trọng.

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

Triển khai cử chỉ tuỳ chỉnh

Nếu bạn có ý tưởng về các hành động tương tác và cử chỉ tuỳ chỉnh cho trang web của mình, thì có 2 chủ đề cần lưu ý:

  1. Cách hỗ trợ mọi trình duyệt.
  2. Cách duy trì tốc độ khung hình cao.

Trong bài viết này, chúng ta sẽ xem xét chính xác những chủ đề bao gồm API mà chúng ta cần hỗ trợ để đáp ứng tất cả trình duyệt, sau đó đề cập đến cách chúng ta sử dụng những sự kiện này một cách hiệu quả.

Tuỳ thuộc vào thao tác mà bạn muốn thực hiện cử chỉ, có thể bạn muốn người dùng tương tác với một phần tử tại một thời điểm hoặc bạn muốn họ có thể tương tác với nhiều phần tử cùng lúc.

Chúng ta sẽ xem xét 2 ví dụ trong bài viết này, cả hai đều minh hoạ khả năng hỗ trợ cho mọi trình duyệt và cách duy trì tốc độ khung hình cao.

Ảnh GIF mẫu khi chạm vào tài liệu

Ví dụ đầu tiên sẽ cho phép người dùng tương tác với một phần tử. Trong trường hợp này, bạn có thể muốn cấp tất cả sự kiện chạm cho một phần tử đó, miễn là cử chỉ ban đầu đã bắt đầu trên chính phần tử đó. Ví dụ: việc di chuyển ngón tay ra khỏi phần tử có thể vuốt vẫn có thể điều khiển phần tử đó.

Điều này rất hữu ích vì mang lại sự linh hoạt cao cho người dùng, nhưng hạn chế cách người dùng có thể tương tác với giao diện người dùng của bạn.

Ảnh GIF ví dụ về thao tác chạm vào thành phần

Tuy nhiên, nếu muốn người dùng tương tác với nhiều thành phần cùng một lúc (sử dụng tính năng cảm ứng đa điểm), thì bạn nên hạn chế thao tác chạm đối với thành phần cụ thể đó.

Phương thức này linh hoạt hơn cho người dùng, nhưng làm phức tạp logic thao tác với giao diện người dùng và khó chống chọi với lỗi của người dùng.

Thêm trình nghe sự kiện

Trong Chrome (phiên bản 55 trở lên), Internet Explorer và Edge, bạn nên sử dụng PointerEvents để triển khai các cử chỉ tuỳ chỉnh.

Trong các trình duyệt khác, TouchEventsMouseEvents là phương pháp đúng.

Tính năng tuyệt vời của PointerEvents là hợp nhất nhiều loại phương thức nhập, bao gồm cả các sự kiện nhấp chuột, chạm và bút thành một tập hợp các lệnh gọi lại. Các sự kiện cần theo dõi là pointerdown, pointermove, pointeruppointercancel.

Các trình duyệt tương đương trong các trình duyệt khác là touchstart, touchmove, touchendtouchcancel cho các sự kiện chạm. Nếu muốn triển khai cùng một cử chỉ để nhập bằng chuột, bạn cần triển khai mousedown, mousemovemouseup.

Nếu bạn có thắc mắc về những sự kiện nên sử dụng, hãy xem bảng các sự kiện cho thao tác chạm, chuột và con trỏ.

Để sử dụng những sự kiện này, bạn phải gọi phương thức addEventListener() trên phần tử DOM, cùng với tên của sự kiện, hàm callback và giá trị boolean. Boolean xác định xem bạn nên nắm bắt sự kiện trước hay sau khi các phần tử khác có cơ hội nắm bắt và diễn giải các sự kiện đó. (true có nghĩa là bạn muốn sự kiện xuất hiện trước các phần tử khác.)

Dưới đây là ví dụ về cách lắng nghe khi bắt đầu một tương tác.

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

Thử nào

Xử lý tương tác một phần tử

Trong đoạn mã ngắn ở trên, chúng tôi chỉ thêm trình nghe sự kiện bắt đầu cho các sự kiện chuột. Lý do là các sự kiện chuột sẽ chỉ kích hoạt khi con trỏ di qua phần tử mà trình nghe sự kiện được thêm vào.

TouchEvents sẽ theo dõi một cử chỉ sau khi cử chỉ bắt đầu bất kể vị trí xảy ra thao tác chạm và PointerEvents sẽ theo dõi các sự kiện bất kể vị trí xảy ra thao tác chạm sau khi chúng ta gọi setPointerCapture trên phần tử DOM.

Đối với các sự kiện kết thúc và sự kiện di chuyển chuột, chúng tôi thêm trình nghe sự kiện trong phương thức bắt đầu cử chỉ và thêm trình nghe vào tài liệu, nghĩa là trình nghe có thể theo dõi con trỏ cho đến khi cử chỉ hoàn tất.

Các bước cần thực hiện để triển khai việc này là:

  1. Thêm tất cả trình nghe TouchEvent và PointerEvent. Đối với MouseEvents, chỉ thêm sự kiện bắt đầu.
  2. Bên trong lệnh gọi lại cử chỉ bắt đầu, hãy liên kết các sự kiện di chuyển chuột và kết thúc với tài liệu. Bằng cách này, bạn sẽ nhận được mọi sự kiện chuột bất kể sự kiện đó có xảy ra trên phần tử gốc hay không. Đối với PointerEvents, chúng tôi cần gọi setPointerCapture() trên phần tử ban đầu để nhận tất cả các sự kiện khác. Sau đó, xử lý điểm bắt đầu cử chỉ.
  3. Xử lý các sự kiện di chuyển.
  4. Ở sự kiện kết thúc, hãy xoá trình nghe kết thúc và di chuyển chuột khỏi tài liệu rồi kết thúc cử chỉ.

Dưới đây là một đoạn mã của phương thức handleGestureStart(). Đoạn mã này sẽ thêm các sự kiện di chuyển và kết thúc vào tài liệu:

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

Thử nào

Lệnh gọi lại kết thúc mà chúng ta thêm là handleGestureEnd(). Lệnh gọi lại này sẽ xoá trình nghe sự kiện di chuyển và kết thúc khỏi tài liệu, đồng thời giải phóng thao tác chụp con trỏ khi cử chỉ kết thúc như sau:

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

Thử nào

Bằng cách làm theo mẫu thêm sự kiện di chuyển này vào tài liệu, nếu người dùng bắt đầu tương tác với một phần tử và di chuyển cử chỉ của họ ra bên ngoài phần tử đó, thì chúng ta sẽ tiếp tục nhận được thao tác di chuyển chuột bất kể chúng đang ở đâu trên trang vì tài liệu đang nhận các sự kiện.

Sơ đồ này cho thấy hoạt động của các sự kiện chạm khi chúng ta thêm sự kiện di chuyển và kết thúc vào tài liệu sau khi một cử chỉ bắt đầu.

Minh hoạ các sự kiện chạm liên kết với tài liệu trong `Touchstart`

Phản hồi thao tác chạm hiệu quả

Giờ đây, khi đã xử lý các sự kiện bắt đầu và kết thúc, chúng ta có thể thực sự phản hồi các sự kiện chạm.

Đối với mọi sự kiện bắt đầu và di chuyển, bạn có thể dễ dàng trích xuất xy từ một sự kiện.

Ví dụ sau đây sẽ kiểm tra xem sự kiện có đến từ TouchEvent hay không bằng cách kiểm tra xem targetTouches có tồn tại hay không. Nếu có, thì công cụ sẽ trích xuất clientXclientY ngay từ lần chạm đầu tiên. Nếu sự kiện là PointerEvent hoặc MouseEvent, thì nó sẽ trích xuất clientXclientY trực tiếp từ chính sự kiện đó.

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

Thử nào

TouchEvent có 3 danh sách chứa dữ liệu cảm ứng:

  • touches: danh sách tất cả các thao tác chạm hiện tại trên màn hình, bất kể các thao tác đó đang bật phần tử DOM nào.
  • targetTouches: danh sách các thao tác chạm hiện tại trên phần tử DOM mà sự kiện liên kết với.
  • changedTouches: danh sách các lần chạm đã thay đổi dẫn đến sự kiện được kích hoạt.

Trong hầu hết trường hợp, targetTouches sẽ cung cấp cho bạn mọi thứ bạn cần và mong muốn. (Để biết thêm thông tin về các danh sách này, hãy xem phần Danh sách cảm ứng).

Sử dụng requestAnimationFrame

Vì các lệnh gọi lại sự kiện được kích hoạt trên luồng chính, nên chúng ta cần chạy càng ít mã càng tốt trong các lệnh gọi lại cho các sự kiện của mình, giữ cho tốc độ khung hình cao và ngăn hiện tượng giật.

Bằng cách sử dụng requestAnimationFrame(), chúng ta có cơ hội cập nhật giao diện người dùng ngay trước khi trình duyệt có ý định vẽ một khung và sẽ giúp di chuyển một số công việc khỏi các lệnh gọi lại sự kiện.

Nếu chưa quen với requestAnimationFrame(), bạn có thể tìm hiểu thêm tại đây.

Cách triển khai điển hình là lưu các toạ độ xy từ các sự kiện bắt đầu và di chuyển, đồng thời yêu cầu một khung ảnh động bên trong lệnh gọi lại sự kiện di chuyển.

Trong bản minh hoạ, chúng ta lưu trữ vị trí chạm ban đầu trong handleGestureStart() (tìm 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);

Phương thức handleGestureMove() lưu trữ vị trí của sự kiện trước khi yêu cầu khung ảnh động nếu cần, truyền vào hàm onAnimFrame() dưới dạng lệnh gọi lại:

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

  if (!initialTouchPos) {
    return;
  }

  lastTouchPos = getGesturePointFromEvent(evt);

  if (rafPending) {
    return;
  }

  rafPending = true;

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

Giá trị onAnimFrame là một hàm mà khi được gọi, sẽ thay đổi giao diện người dùng để di chuyển giao diện người dùng xung quanh. Khi chuyển hàm này vào requestAnimationFrame(), chúng ta sẽ yêu cầu trình duyệt gọi hàm này ngay trước khi cập nhật trang (tức là vẽ mọi thay đổi trên trang).

Trong lệnh gọi lại handleGestureMove(), ban đầu chúng tôi kiểm tra xem rafPending có phải là sai hay không. Điều này cho biết liệu onAnimFrame() có được requestAnimationFrame() gọi kể từ sự kiện di chuyển gần đây nhất hay không. Điều này có nghĩa là chúng tôi chỉ có một requestAnimationFrame() đang chờ để chạy tại một thời điểm bất kỳ.

Khi thực thi lệnh gọi lại onAnimFrame(), chúng ta đặt phép biến đổi trên mọi phần tử mà chúng ta muốn di chuyển trước khi cập nhật rafPending thành false, cho phép sự kiện chạm tiếp theo yêu cầu một khung ảnh động mới.

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

Điều khiển cử chỉ bằng thao tác chạm

Thuộc tính CSS touch-action cho phép bạn kiểm soát hành vi chạm mặc định của một phần tử. Trong ví dụ này, chúng ta sử dụng touch-action: none để ngăn trình duyệt thực hiện bất kỳ hành động nào với thao tác chạm của người dùng, cho phép chúng ta chặn tất cả các sự kiện chạm.

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

Việc sử dụng touch-action: none có phần không phù hợp vì lựa chọn này ngăn chặn tất cả các hành vi mặc định của trình duyệt. Trong nhiều trường hợp, bạn nên chọn một trong các phương án dưới đây.

touch-action cho phép bạn tắt các cử chỉ do trình duyệt triển khai. Ví dụ: IE10+ hỗ trợ cử chỉ nhấn đúp để thu phóng. Bằng cách đặt touch-actionmanipulation, bạn sẽ ngăn chặn hành vi nhấn đúp mặc định.

Thao tác này cho phép bạn tự triển khai cử chỉ nhấn đúp.

Dưới đây là danh sách các giá trị touch-action thường dùng:

Thông số hành động chạm
touch-action: none Trình duyệt sẽ không xử lý bất kỳ tương tác chạm nào.
touch-action: pinch-zoom Vô hiệu hoá mọi hoạt động tương tác trên trình duyệt như "thao tác chạm: không có" ngoại trừ "chụm-thu phóng" (hiện vẫn do trình duyệt xử lý).
touch-action: pan-y pinch-zoom Xử lý các thao tác cuộn ngang trong JavaScript mà không cần tắt tính năng cuộn dọc hoặc chụm/thu phóng (ví dụ: băng chuyền hình ảnh).
touch-action: manipulation Tắt cử chỉ nhấn đúp để tránh mọi độ trễ nhấp của trình duyệt. Thoát thao tác cuộn và chụm-mở rộng lên trình duyệt.

Hỗ trợ các phiên bản cũ hơn của IE

Nếu muốn hỗ trợ IE10, bạn cần phải xử lý các phiên bản PointerEvents có tiền tố nhà cung cấp.

Để kiểm tra khả năng hỗ trợ của PointerEvents, thường thì bạn sẽ tìm window.PointerEvent, nhưng trong IE10, bạn sẽ tìm window.navigator.msPointerEnabled.

Tên sự kiện có tiền tố nhà cung cấp là: 'MSPointerDown', 'MSPointerUp''MSPointerMove'.

Ví dụ bên dưới cho bạn biết cách kiểm tra khả năng hỗ trợ và chuyển đổi tên sự kiện.

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

Để biết thêm thông tin, hãy xem bài viết này về bản cập nhật của Microsoft.

Tài liệu tham khảo

Lớp giả cho trạng thái cảm ứng

Lớp Ví dụ: Nội dung mô tả
:hover
Nút ở trạng thái nhấn
Được nhập khi con trỏ được đặt lên một phần tử. Những thay đổi trên giao diện người dùng khi di chuột là rất hữu ích trong việc khuyến khích người dùng tương tác với các phần tử.
:tập trung
Nút có trạng thái lấy nét
Được nhập khi người dùng nhấn vào các phần tử trên một trang. Trạng thái tiêu điểm cho phép người dùng biết họ đang tương tác với thành phần nào; cũng cho phép người dùng dễ dàng di chuyển trên giao diện người dùng của bạn bằng bàn phím.
:đang hoạt động
Nút ở trạng thái nhấn
Được nhập khi một phần tử đang được chọn, ví dụ: khi người dùng nhấp hoặc chạm vào một phần tử.

Bạn có thể xem tài liệu tham khảo về sự kiện chạm cuối cùng tại đây: Sự kiện chạm W3C.

Các sự kiện chạm, chuột và con trỏ

Những sự kiện này là yếu tố nền tảng để thêm các cử chỉ mới vào ứng dụng của bạn:

Sự kiện chạm, chuột, con trỏ
touchstart, mousedown, pointerdown Lệnh này được gọi khi ngón tay chạm vào một phần tử lần đầu tiên hoặc khi người dùng nhấp chuột xuống.
touchmove, mousemove, pointermove Lệnh này được gọi khi người dùng di chuyển ngón tay trên màn hình hoặc kéo bằng chuột.
touchend, mouseup, pointerup Lệnh này được gọi khi người dùng nhấc ngón tay ra khỏi màn hình hoặc thả chuột ra.
touchcancel pointercancel Lệnh này được gọi khi trình duyệt huỷ các cử chỉ chạm. Ví dụ: người dùng chạm vào một ứng dụng web rồi thay đổi các thẻ.

Danh sách cảm ứng

Mỗi sự kiện chạm bao gồm ba thuộc tính danh sách:

Thuộc tính sự kiện chạm
touches Danh sách tất cả các thao tác chạm hiện tại trên màn hình, bất kể thành phần nào bạn đang chạm vào.
targetTouches Danh sách các thao tác chạm bắt đầu trên phần tử là mục tiêu của sự kiện hiện tại. Ví dụ: nếu liên kết với một <button>, bạn sẽ chỉ thực hiện các thao tác chạm trên nút đó. Nếu liên kết với tài liệu, bạn sẽ thực hiện được tất cả thao tác hiện tại trên tài liệu.
changedTouches Danh sách các thao tác chạm đã thay đổi dẫn đến việc sự kiện được kích hoạt:
  • Đối với sự kiện touchstart-- danh sách các điểm tiếp xúc vừa hoạt động với sự kiện hiện tại.
  • Đối với sự kiện touchmove-- danh sách các điểm tiếp xúc đã di chuyển kể từ sự kiện gần đây nhất.
  • Đối với các sự kiện touchend touchcancel – danh sách các điểm chạm vừa bị xoá khỏi nền tảng.

Bật tính năng hỗ trợ trạng thái đang hoạt động trên iOS

Rất tiếc, Safari trên iOS không áp dụng trạng thái đang hoạt động theo mặc định. Để ứng dụng này hoạt động, bạn cần thêm trình nghe sự kiện touchstart vào phần nội dung tài liệu hoặc cho từng phần tử.

Bạn nên thực hiện việc này sau một bài kiểm thử tác nhân người dùng để mã này chỉ chạy trên thiết bị iOS.

Việc thêm bắt đầu chạm vào phần nội dung có lợi thế là áp dụng cho tất cả các phần tử trong DOM. Tuy nhiên, việc này có thể gây ra vấn đề về hiệu suất khi cuộn trang.

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

Một cách khác là thêm trình nghe bắt đầu thao tác chạm vào tất cả các phần tử có thể tương tác trên trang, giúp giảm bớt một số vấn đề về hiệu suất.

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