Phát triển web đa điểm

Boris Smus
Boris Smus

Giới thiệu

Các thiết bị di động như điện thoại thông minh và máy tính bảng thường có màn hình cảm ứng điện dung để ghi lại các hoạt động tương tác được thực hiện bằng ngón tay của người dùng. Khi web dành cho thiết bị di động phát triển để cho phép các ứng dụng ngày càng phức tạp, nhà phát triển web cần có cách để xử lý các sự kiện này. Ví dụ: gần như mọi trò chơi có tốc độ nhanh đều yêu cầu người chơi nhấn nhiều nút cùng một lúc. Điều này ngụ ý tính năng cảm ứng đa điểm.

Apple đã giới thiệu API sự kiện chạm trong iOS 2.0. Android đã và đang bắt kịp tiêu chuẩn thực tế này và thu hẹp khoảng cách. Gần đây, một nhóm làm việc W3C đã cùng nhau để xử lý thông số kỹ thuật về sự kiện chạm này.

Trong bài viết này, tôi sẽ đi sâu vào API sự kiện chạm do các thiết bị iOS và Android cung cấp, cũng như Chrome dành cho máy tính trên phần cứng hỗ trợ thao tác chạm và khám phá những loại ứng dụng bạn có thể xây dựng, giới thiệu một số phương pháp hay nhất và đề cập đến các kỹ thuật hữu ích giúp phát triển các ứng dụng có hỗ trợ cảm ứng dễ dàng hơn.

Sự kiện chạm

Ba sự kiện chạm cơ bản được nêu trong thông số kỹ thuật và được triển khai rộng rãi trên các thiết bị di động:

  • Touchstart: một ngón tay được đặt trên phần tử DOM.
  • Touchmove: một ngón tay được kéo dọc theo phần tử DOM.
  • Touchend: một ngón tay bị xoá khỏi phần tử DOM.

Mỗi sự kiện chạm bao gồm ba danh sách lần chạm:

  • chạm: danh sách tất cả các ngón tay hiện có trên màn hình.
  • targetTouches: danh sách các ngón tay trên phần tử DOM hiện tại.
  • changedTouches: danh sách các ngón tay liên quan đến sự kiện hiện tại. Ví dụ: trong một sự kiện chạm, đây sẽ là ngón tay đã bị xóa.

Các danh sách này bao gồm các đối tượng chứa thông tin chạm:

  • identifier: một số nhận dạng duy nhất ngón tay hiện tại trong phiên chạm.
  • target: phần tử DOM từng là mục tiêu của hành động.
  • tọa độ ứng dụng khách/trang/màn hình: vị trí diễn ra hành động trên màn hình.
  • tọa độ bán kính và góc xoay: mô tả hình elip gần đúng hình dạng ngón tay.

Ứng dụng có hỗ trợ cảm ứng

Các sự kiện Touchstart, TouchmoveTouchend cung cấp một bộ tính năng đủ phong phú để hỗ trợ hầu hết mọi loại tương tác dựa trên thao tác chạm – bao gồm tất cả cử chỉ nhiều điểm chạm thông thường như chụm – thu phóng, xoay, v.v.

Đoạn mã này cho phép bạn kéo phần tử DOM xung quanh bằng cách chạm bằng một ngón tay:

var obj = document.getElementById('id');
obj.addEventListener('touchmove', function(event) {
  // If there's exactly one finger inside this element
  if (event.targetTouches.length == 1) {
    var touch = event.targetTouches[0];
    // Place element where the finger is
    obj.style.left = touch.pageX + 'px';
    obj.style.top = touch.pageY + 'px';
  }
}, false);

Dưới đây là mẫu cho thấy tất cả các thao tác chạm hiện tại trên màn hình. Bạn chỉ cần biết cảm nhận về khả năng phản hồi của thiết bị.

Tính năng theo dõi ngón tay.
// Setup canvas and expose context via ctx variable
canvas.addEventListener('touchmove', function(event) {
  for (var i = 0; i < event.touches.length; i++) {
    var touch = event.touches[i];
    ctx.beginPath();
    ctx.arc(touch.pageX, touch.pageY, 20, 0, 2*Math.PI, true);
    ctx.fill();
    ctx.stroke();
  }
}, false);

Bản thu thử

Một số bản minh hoạ cảm ứng đa điểm thú vị đã có sẵn, chẳng hạn như bản minh hoạ vẽ dựa trên canvas của Paul Ireland và những người khác.

Ảnh chụp màn hình bản vẽ

Browser Ninja, một bản minh hoạ công nghệ là bản sao của Fruit Ninja sử dụng tính năng biến đổi và chuyển đổi CSS3, cũng như canvas:

Ninja trình duyệt

Các phương pháp hay nhất

Ngăn thu phóng

Các chế độ cài đặt mặc định hoạt động không hiệu quả đối với chế độ cảm ứng đa điểm, vì các thao tác vuốt và cử chỉ thường liên quan đến hành vi của trình duyệt, chẳng hạn như thao tác cuộn và thu phóng.

Để tắt tính năng thu phóng, hãy thiết lập khung nhìn sao cho người dùng không thể mở rộng bằng cách sử dụng thẻ meta sau:

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

Xem bài viết về HTML5 dành cho thiết bị di động này để biết thêm thông tin về cách cài đặt khung nhìn của bạn.

Ngăn cuộn

Một số thiết bị di động có hành vi mặc định cho thao tác di chuyển bằng thao tác chạm, chẳng hạn như hiệu ứng cuộn quá mức kiểu cũ của iOS, khiến khung hiển thị bật trở lại khi cuộn vượt quá giới hạn của nội dung. Điều này gây nhầm lẫn trong nhiều ứng dụng đa điểm và có thể dễ dàng bị tắt:

document.body.addEventListener('touchmove', function(event) {
  event.preventDefault();
}, false); 

Kết xuất cẩn thận

Nếu bạn đang viết một ứng dụng nhiều điểm chạm có liên quan đến các cử chỉ nhiều ngón tay phức tạp, hãy cẩn thận về cách bạn phản ứng với các sự kiện chạm, vì bạn sẽ phải xử lý nhiều sự kiện cùng lúc. Hãy xem xét mẫu ở phần trước vẽ tất cả các điểm chạm trên màn hình. Bạn có thể vẽ ngay khi có một thao tác nhập bằng cách chạm:

canvas.addEventListener('touchmove', function(event) {
  renderTouches(event.touches);
}, false);

Tuy nhiên, kỹ thuật này không điều chỉnh được theo số lượng ngón tay trên màn hình. Thay vào đó, bạn có thể theo dõi tất cả các ngón tay và kết xuất trong một vòng lặp để đạt được hiệu suất tốt hơn nhiều:

var touches = []
canvas.addEventListener('touchmove', function(event) {
  touches = event.touches;
}, false);

// Setup a 60fps timer
timer = setInterval(function() {
  renderTouches(touches);
}, 15);

Sử dụng targetTouches và changesTouches

Hãy nhớ event.Touches là một mảng gồm TẤT CẢ ngón tay tiếp xúc với màn hình, chứ không chỉ các ngón tay trên mục tiêu của phần tử DOM. Thay vào đó, bạn nên sử dụng event.targetTouches hoặc event.replaceTouches sẽ hữu ích hơn nhiều.

Cuối cùng, vì bạn đang phát triển cho thiết bị di động, bạn nên lưu ý về các phương pháp chung hay nhất cho thiết bị di động, được đề cập trong bài viết của Eric Bidelman, cũng như tài liệu W3C này.

Hỗ trợ về thiết bị

Rất tiếc, việc triển khai sự kiện chạm khác nhau đáng kể về mức độ hoàn chỉnh và chất lượng. Tôi đã viết một tập lệnh chẩn đoán hiển thị một số thông tin cơ bản về việc triển khai API cảm ứng, bao gồm cả những sự kiện được hỗ trợ và độ phân giải kích hoạt di chuyển bằng cách chạm. Tôi đã thử nghiệm Android 2.3.3 trên phần cứng Nexus One và Nexus S, Android 3.0.1 trên Xoom và iOS 4.2 trên iPad và iPhone.

Tóm lại, tất cả các trình duyệt được thử nghiệm đều hỗ trợ các sự kiện Touchstart, TouchendTouchmove.

Thông số kỹ thuật này cung cấp thêm 3 sự kiện chạm, nhưng không có trình duyệt nào được thử nghiệm hỗ trợ:

  • Touchenter: ngón tay di chuyển nhập vào phần tử DOM.
  • chờ: ngón tay di chuyển rời khỏi phần tử DOM.
  • Touchcancel: một thao tác chạm bị gián đoạn (triển khai cụ thể).

Trong mỗi danh sách cảm ứng, các trình duyệt được kiểm thử cũng cung cấp các danh sách cảm ứng Touches (Chạm), targetTouchesChangesTouches. Tuy nhiên, không có trình duyệt được thử nghiệm nào hỗ trợ salesX, SellerY hoặc rotationAngle. Các trình duyệt này chỉ định hình dạng của ngón tay chạm vào màn hình.

Trong một lần di chuyển, các sự kiện sẽ kích hoạt với tốc độ khoảng 60 lần/giây trên tất cả các thiết bị được thử nghiệm.

Android 2.3.3 (Nexus)

Trên Trình duyệt Android Gingerbread (thử nghiệm trên Nexus One và Nexus S), không có hỗ trợ cảm ứng đa điểm. Đây là vấn đề đã biết.

Android 3.0.1 (Xoom)

Trên trình duyệt của Xoom có hỗ trợ cảm ứng đa điểm cơ bản, nhưng nó chỉ hoạt động trên một phần tử DOM duy nhất. Trình duyệt không phản hồi chính xác với hai lần chạm đồng thời trên các phần tử DOM khác nhau. Nói cách khác, hoạt động sau đây sẽ phản ứng với hai lần chạm đồng thời:

obj1.addEventListener('touchmove', function(event) {
  for (var i = 0; i < event.targetTouches; i++) {
    var touch = event.targetTouches[i];
    console.log('touched ' + touch.identifier);
  }
}, false);

Nhưng những trường hợp sau sẽ không:

var objs = [obj1, obj2];
for (var i = 0; i < objs.length; i++) {
  var obj = objs[i];
  obj.addEventListener('touchmove', function(event) {
    if (event.targetTouches.length == 1) {
      console.log('touched ' + event.targetTouches[0].identifier);
    }
  }, false);
}

iOS 4.x (iPad, iPhone)

Thiết bị iOS hỗ trợ đầy đủ chế độ cảm ứng đa điểm, có khả năng theo dõi khá nhiều ngón tay và cung cấp trải nghiệm cảm ứng rất phản hồi trong trình duyệt.

Công cụ dành cho nhà phát triển

Trong quá trình phát triển cho thiết bị di động, thường sẽ dễ dàng hơn khi bắt đầu tạo nguyên mẫu trên máy tính, sau đó xử lý các phần dành riêng cho thiết bị di động trên các thiết bị bạn định hỗ trợ. Cảm ứng đa điểm là một trong những tính năng khó kiểm thử trên máy tính, vì hầu hết máy tính không có phương thức nhập bằng cách chạm.

Việc phải kiểm thử trên thiết bị di động có thể kéo dài chu kỳ phát triển của bạn, vì mọi thay đổi bạn thực hiện cần được đẩy ra máy chủ rồi tải trên thiết bị. Sau đó, khi chạy, bạn không thể làm gì để gỡ lỗi ứng dụng của mình, vì máy tính bảng và điện thoại thông minh thiếu công cụ dành cho nhà phát triển web.

Giải pháp cho vấn đề này là mô phỏng các sự kiện chạm trên máy phát triển của bạn. Đối với thao tác nhấn một lần, các sự kiện nhấn có thể được mô phỏng dựa trên các sự kiện chuột. Các sự kiện nhiều điểm chạm có thể được mô phỏng nếu bạn có thiết bị hỗ trợ phương thức nhập bằng cách chạm, chẳng hạn như MacBook hiện đại của Apple.

Sự kiện bằng một lần nhấn

Nếu bạn muốn mô phỏng các sự kiện nhấn một lần trên máy tính, Chrome sẽ cung cấp quy trình mô phỏng sự kiện nhấn qua các công cụ cho nhà phát triển. Mở Công cụ cho nhà phát triển, chọn bánh răng Cài đặt, sau đó chọn "Ghi đè" hoặc "Mô phỏng" rồi bật chế độ "Mô phỏng sự kiện chạm".

Đối với các trình duyệt khác, bạn có thể muốn dùng thử Phantom Limb, ứng dụng này mô phỏng các sự kiện chạm trên trang và cũng cung cấp một bàn tay lớn để khởi động.

Ngoài ra, trình bổ trợ jQuery có thể chạm giúp hợp nhất các sự kiện chạm và chuột trên các nền tảng.

Sự kiện nhiều điểm chạm

Để ứng dụng web cảm ứng đa điểm hoạt động trong trình duyệt trên bàn di chuột đa điểm chạm (chẳng hạn như MacBook hoặc MagicPad của Apple), tôi đã tạo polyfill MagicTouch.js. Tính năng này ghi lại các sự kiện chạm từ bàn di chuột và chuyển các sự kiện đó thành các sự kiện chạm tương thích tiêu chuẩn.

  1. Tải xuống và cài đặt trình bổ trợ hreflang npTuioClient vào ~/Library/Internet Plugin-Ins/.
  2. Tải ứng dụng TongSeng TUIO cho MagicPad của máy Mac và khởi động máy chủ.
  3. Tải MagicTouch.js xuống, một thư viện javascript để mô phỏng các sự kiện chạm tương thích với thông số kỹ thuật dựa trên lệnh gọi lại npTuioClient.
  4. Bao gồm tập lệnh ma thuậtTouch.js và trình bổ trợ npTuioClient trong ứng dụng của bạn như sau:
<head>
  ...
  <script src="/path/to/magictouch.js"></script>
</head>

<body>
  ...
  <object id="tuio" type="application/x-tuio" style="width: 0px; height: 0px;">
    Touch input plugin failed to load!
  </object>
</body>

Bạn có thể cần bật trình bổ trợ này.

Bạn có thể xem bản minh hoạ trực tiếp với ma thuật điểm.js tại paulirish.com/demo/multi:

Tôi chỉ thử nghiệm phương pháp này với Chrome 10, nhưng nó sẽ hoạt động trên các trình duyệt hiện đại khác chỉ với một số điều chỉnh nhỏ.

Nếu máy tính của bạn không có phương thức nhập đa điểm, bạn có thể mô phỏng các sự kiện chạm bằng cách sử dụng các trình theo dõi TUIO khác, chẳng hạn như reacTIVision. Để biết thêm thông tin, hãy xem trang dự án TUIO.

Lưu ý rằng cử chỉ của bạn có thể giống với cử chỉ nhiều điểm chạm ở cấp hệ điều hành. Trên OS X, bạn có thể định cấu hình các sự kiện trên toàn hệ thống bằng cách chuyển đến ngăn lựa chọn ưu tiên Bàn di chuột trong phần Tuỳ chọn hệ thống.

Khi tính năng cảm ứng đa điểm được hỗ trợ rộng rãi hơn trên các trình duyệt cho thiết bị di động, tôi rất vui khi thấy các ứng dụng web mới tận dụng tối đa API phong phú này.