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 để hỗ trợ các ứng dụng ngày càng tinh vi, các nhà phát triển web cần có cách xử lý những sự kiện này. Ví dụ: hầu hết 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. Trong bối cảnh màn hình cảm ứng, điều này có nghĩa là nhiều điểm chạm.
Apple đã ra mắt API sự kiện chạm trong iOS 2.0. Android đ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 của W3C đã cùng nhau làm việc về thông số kỹ thuật của 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 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ợ cảm ứng, đồng thời khám phá các loại ứng dụng mà bạn có thể tạo, trình bày một số phương pháp hay nhất và trình bày các kỹ thuật hữu ích giúp phát triển các ứng dụng 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: ngón tay bị xoá khỏi phần tử DOM.
Mỗi sự kiện chạm bao gồm 3 danh sách các lần chạm:
- touches: danh sách tất cả các ngón tay hiện đang ở 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 tham gia vào sự kiện hiện tại. Ví dụ: trong sự kiện chạm vào cuối, đây sẽ là ngón tay đã bị xoá.
Các danh sách này bao gồm các đối tượng chứa thông tin chạm:
- mã nhận dạng: 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 là mục tiêu của thao tác.
- tọa độ máy khách/trang/màn hình: vị trí trên màn hình mà hành động xảy ra.
- toạ độ bán kính và góc xoay: mô tả hình elip gần đúng với hình dạng ngón tay.
Ứng dụng hỗ trợ cảm ứng
Các sự kiện touchstart, touchmove và touchend 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 cảm ứng – bao gồm tất cả các cử chỉ cảm ứng đa điể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 sử dụng thao tác chạm 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ột 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. Việc này rất hữu ích để biết được khả năng phản hồi của thiết bị.
// 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ạ bản vẽ dựa trên canvas này của Paul Ireland và những người khác.
Và Browser Ninja, một bản minh hoạ công nghệ là bản sao của từ trái quả Ninja sử dụng các biến đổi và chuyển đổi CSS3 cũng như canvas:
Các phương pháp hay nhất
Ngăn thu phóng
Chế độ cài đặt mặc định không hoạt động tốt đối với tính năng cảm ứng đa điểm, vì các thao tác vuốt và cử chỉ thường được liên kết với hành vi của trình duyệt, chẳng hạn như cuộn và thu phóng.
Để tắt tính năng thu phóng, hãy thiết lập khung nhìn của bạn để người dùng không thể điều chỉnh theo tỷ lệ 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 đặ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 touchmove, chẳng hạn như hiệu ứng cuộn quá mức iOS cổ điển, khiến khung hiển thị bật 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 cảm ứ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 cảm ứng đa điểm có liên quan đến các cử chỉ phức tạp bằng nhiều ngón tay, hãy cẩn thận với cách bạn phản ứng với các sự kiện chạm, vì bạn sẽ xử lý nhiều sự kiện cùng một lúc. Hãy xem xét mẫu trong phần trước đó vẽ tất cả các thao tác chạm trên màn hình. Bạn có thể vẽ ngay khi có 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 theo số 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à changedTouches
Hãy nhớ rằng event.touches là một mảng gồm TẤT CẢ các ngón tay tiếp xúc với màn hình, chứ không chỉ những ngón tay trên mục tiêu của phần tử DOM. Bạn có thể thấy việc sử dụng event.targetTouches hoặc event.changedTouches 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, nên bạn nên nắm được các phương pháp chung hay nhất về 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ị
Thật không may, việc triển khai sự kiện chạm có sự khác biệt đá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ả các sự kiện được hỗ trợ và độ phân giải kích hoạt touchmove. Tôi đã kiểm thử 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ả trình duyệt đã kiểm thử đều hỗ trợ các sự kiện Touchstart, Touchend và Touchmove.
Quy cách 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 kiểm thử hỗ trợ các sự kiện này:
- touchenter: ngón tay di chuyển vào một phần tử DOM.
- touchleave: ngón tay di chuyển rời khỏi một phần tử DOM.
- touchcancel: thao tác chạm bị gián đoạn (tuỳ thuộc vào cách triển khai).
Trong mỗi danh sách cảm ứng, trình duyệt được kiểm thử cũng cung cấp các danh sách cảm ứng Touches (Chạm), targetTouches và changeTouches (thay đổi). Tuy nhiên, không có trình duyệt nào được kiểm thử hỗ trợ radiusX, radiusY hoặc rotationAngle, các thông số này chỉ định hình dạng của ngón tay chạm vào màn hình.
Trong một thao tác chạm và di chuyển, các sự kiện sẽ kích hoạt với tần suất khoảng 60 lần/giây trên tất cả thiết bị được kiểm thử.
Android 2.3.3 (Nexus)
Trên Trình duyệt Gingerbread dành cho Android (đã thử nghiệm trên Nexus One và Nexus S), không có tính năng 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 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 hai thao tác chạm đồng thời trên các phần tử DOM khác nhau. Nói cách khác, thao tác sau đây sẽ phản ứng với 2 thao tác nhấn đồ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 nội dung sau đây sẽ không được hỗ trợ:
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)
Các thiết bị iOS hỗ trợ đầy đủ tính năng cảm ứng đa điểm, có thể theo dõi khá nhiều ngón tay và mang lại trải nghiệm cảm ứng rất nhạy trong trình duyệt.
Công cụ dành cho nhà phát triển
Trong quá trình phát triển ứng dụng di động, bạn thường dễ dàng bắt đầu tạo bản minh hoạ trên máy tính rồi xử lý các phần dành riêng cho thiết bị di động trên các thiết bị mà bạn dự đị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ó chế độ 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, vì mọi thay đổi bạn thực hiện đều cần được đẩy ra máy chủ rồi tải lên thiết bị. Sau đó, khi chạy, bạn không thể làm gì để gỡ lỗi ứng dụng 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. Đối với thao tác chạm một lần, bạn có thể mô phỏng sự kiện chạm dựa trên sự kiện chuột. Các sự kiện cảm ứng đa điểm có thể được mô phỏng nếu bạn sở hữu thiết bị có tính năng nhập bằng cách chạm, chẳng hạn như Apple MacBook hiện đại.
Sự kiện nhấn một lầ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 tính năng mô phỏng sự kiện chạm từ các công cụ dành cho nhà phát triển. Mở Công cụ dành cho nhà phát triển, sau đó chọn biểu tượng bánh răng Cài đặt, rồi chọn "Ghi đè" hoặc "Mô phỏng" và bật "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, một công cụ mô phỏng các sự kiện chạm trên trang và cũng cho phép bạn khởi động mạnh mẽ.
Ngoài ra, trình bổ trợ jQuery Touchable còn hợp nhất các sự kiện chạm và sự kiện chuột trên các nền tảng.
Sự kiện cảm ứng đa điểm
Để cho phép ứ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 cảm ứng đa điểm (chẳng hạn như Apple MacBook hoặc MagicPad), tôi đã tạo MagicTouch.js polyfill. Lớp này ghi lại các sự kiện chạm từ bàn di chuột và biến chúng thành các sự kiện chạm tương thích với tiêu chuẩn.
- Tải xuống và cài đặt trình bổ trợ NPAPI npTuioClient vào ~/Library/Internet Plug-Ins/.
- Tải ứng dụng TongSeng TUIO cho MagicPad của máy Mac rồi khởi động máy chủ.
- Tải MagicTouch.js, 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.
- Thêm tập lệnh magictouch.js và trình bổ trợ npTuioClient vào ứng dụng 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 phải bật trình bổ trợ này.
Bạn có thể xem bản minh hoạ trực tiếp với magictouch.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 phương pháp này 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 nhiều điểm chạ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.
Xin 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 các 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 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.