Một nhà phát triển xây dựng phát hiện thu phóng hai ngón tay sử dụng TouchEvent sẽ gửi mã hoạt động hoàn hảo trên điện thoại Android và im lặng không làm gì trên laptop Windows. Lý do là kiến trúc, không phải lỗi trình duyệt: bàn di chuột máy tính để bàn hoàn toàn không phát ra TouchEvent. Biết được sự kiện nào mỗi thiết bị đầu vào thực sự tạo ra — và tại sao — là điều kiện tiên quyết để viết mã cử chỉ hoạt động trên nhiều loại thiết bị.
PointerEvent và TouchEvent là gì
TouchEvent là API cũ hơn trong hai API. Được giới thiệu để xử lý đầu vào ngón tay trên màn hình cảm ứng di động, nó cung cấp danh sách các điểm tiếp xúc đang hoạt động (touches, targetTouches, changedTouches) qua các sự kiện có tên touchstart, touchmove, touchend, và touchcancel. Mỗi mục trong danh sách đó là một đối tượng Touch với tọa độ và định danh riêng. API được thiết kế đặc biệt cho màn hình cảm ứng, và điều đó thể hiện rõ: nó không có khái niệm về chuột, bút cảm ứng hay bàn di chuột.
PointerEvent là sự thay thế hợp nhất của W3C, lần đầu tiên được phát hành trên Internet Explorer 11 và hiện có mặt trên mọi trình duyệt lớn. Nó xử lý chuột, bút và cảm ứng qua một họ sự kiện duy nhất — pointerdown, pointermove, pointerup, pointercancel — và cung cấp thuộc tính pointerType trên mỗi sự kiện để xác định nguồn gốc: "mouse", "pen", hoặc "touch". Tài liệu sự kiện Pointer của MDN mô tả đầy đủ mô hình; đặc tả W3C được duy trì tại w3c.github.io/pointerevents.
Bàn di chuột máy tính để bàn thực sự phát ra gì
Đây là phần khiến nhiều nhà phát triển ngạc nhiên: bàn di chuột laptop trên hệ điều hành máy tính để bàn không phát ra TouchEvent, và không tạo ra PointerEvent với pointerType: "touch". Nó phát ra:
- Sự kiện PointerEvent với
pointerType: "mouse"— chuyển động và nhấp một điểm tiếp xúc đến dưới dạng sự kiện con trỏ chuột thông thường. Trình duyệt không thể phân biệt chỉ qua sự kiện xem thiết bị vật lý là chuột hay bàn di chuột. - Sự kiện WheelEvent — cuộn hai ngón tay trên bàn di chuột tạo ra sự kiện
wheel, giống hệt như bánh xe cuộn chuột. Thuộc tínhdeltaXvàdeltaYbáo cáo lượng cuộn. - Sự kiện WheelEvent với
ctrlKey: true— hệ điều hành chuyển đổi cử chỉ thu phóng bằng hai ngón tay trên bàn di chuột thành sự kiệnwheelvới cờctrlKeyđược bật. Đây là tín hiệu chuẩn đa trình duyệt cho thu phóng điều khiển bằng bàn di chuột. Các trang web chặnctrl+wheelđể thực hiện thu phóng tùy chỉnh đang tận dụng đúng quy ước này.
Ngược lại, màn hình cảm ứng phát ra PointerEvent với pointerType: "touch" — và trên các trình duyệt vẫn duy trì API cũ, còn có TouchEvent. Hai ngón tay trên màn hình cảm ứng tạo ra hai sự kiện pointerdown đồng thời, mỗi sự kiện có pointerId riêng biệt, mà mã web có thể dùng trực tiếp để tính toán tỷ lệ thu phóng bằng cách so sánh khoảng cách giữa các con trỏ.
Tại sao sự phân biệt quan trọng với mã cử chỉ
Hệ quả thực tế chia thành ba mẫu:
- Thu phóng hai ngón tay trên màn hình cảm ứng — phát hiện bằng cách theo dõi hai sự kiện
pointerdownđồng thời (hoặc hai mục trongTouchEvent.touches) và tính khoảng cách giữa chúng qua các sự kiệnpointermove. Mẫu này hoạt động trên di động nhưng không tạo ra gì hữu ích trên bàn di chuột máy tính để bàn, vì bàn di chuột không bao giờ gửi hai điểm tiếp xúc đồng thời đến trình duyệt. - Thu phóng bằng bàn di chuột — chỉ phát hiện qua sự kiện
wheelvớictrlKey === true. Không cần và không thể tính toán hai con trỏ. Hệ điều hành đã chuyển đổi cử chỉ hai ngón thành giá trị thu phóng trước khi trình duyệt nhận được. - Cuộn trên cả hai thiết bị — hội tụ trên cùng sự kiện
wheel, làm cho cuộn trở thành cử chỉ dễ xử lý nhất:addEventListener("wheel", handler)bắt được cuộn hai ngón trên bàn di chuột và cuộn vượt quá trên màn hình cảm ứng một cách đồng đều.
Sự phân chia kiến trúc này là có chủ ý. Hệ điều hành xử lý dữ liệu tiếp xúc đa ngón thô từ bàn di chuột và gửi các sự kiện đã xử lý, có nhãn ngữ nghĩa đến trình duyệt. Trình duyệt sau đó chuyển tiếp các sự kiện đó đến trang web. Ngược lại, màn hình cảm ứng truyền dữ liệu tiếp xúc thô đến trình duyệt, đó là lý do mã web có thể thực hiện logic thu phóng tùy chỉnh trên màn hình cảm ứng nhưng không thể làm điều tương tự trên bàn di chuột máy tính để bàn mà không vượt ra ngoài nền tảng web chuẩn.
Cách công cụ kiểm thử phản ánh thiết kế này
Mô-đun GestureDetector của công cụ kiểm thử sử dụng sự phân chia này một cách có chủ đích. Nhấn, nhấn đúp, nhấn giữ và vuốt được phát hiện qua các trình nghe PointerEvent — cùng sự kiện mà bàn di chuột phát ra dưới dạng pointerType: "mouse". Cuộn được phát hiện qua trình nghe sự kiện wheel. Thu phóng, tuy nhiên, được phát hiện qua TouchEvent (touchstart, touchmove) — cụ thể kiểm tra hai điểm tiếp xúc đồng thời và đo sự thay đổi khoảng cách giữa chúng. Nếu khoảng cách thay đổi hơn 30 pixel, một cử chỉ thu phóng được kích hoạt. Trên bàn di chuột máy tính để bàn, đường dẫn này sẽ không bao giờ kích hoạt vì không có TouchEvent nào đến; thu phóng trên bàn di chuột chỉ đến trình duyệt dưới dạng sự kiện ctrl+wheel, mà bảng cử chỉ đếm vào phần cuộn thay vì thu phóng. Trên màn hình cảm ứng, đường dẫn TouchEvent hoạt động chính xác và bộ đếm thu phóng tăng lên.
Một hạn chế thực tế đáng lưu ý: không API nào cung cấp dữ liệu tiếp xúc ngón tay thô từ bàn di chuột máy tính để bàn đến trang web. Công cụ kiểm thử có thể quan sát sự kiện ctrl+wheel được phát ra, nhưng không thể báo số lượng ngón tay tạo ra nó hay vị trí tiếp xúc thô — thông tin đó đã được hệ điều hành xử lý trước khi đến trình duyệt.
Tự kiểm tra: sử dụng công cụ trên bàn di chuột laptop và thử cử chỉ thu phóng hai ngón tay. Nếu bảng Phát hiện Cử chỉ không tăng bộ đếm thu phóng, bạn đang dùng bàn di chuột máy tính để bàn, nơi thu phóng đến dưới dạngctrl+wheelthay vìTouchEvent. Chuyển sang thiết bị màn hình cảm ứng và lặp lại cử chỉ — bộ đếm thu phóng sẽ tăng, xác nhận đường dẫnTouchEventhai ngón tay đang hoạt động.