Menunjukkan arah ke depan

Sérgio Gomes

Dulunya, menunjuk ke hal-hal di web ternyata mudah. Anda memiliki mouse, Anda memindahkannya sekitar, kadang-kadang Anda menekan tombol, dan itu saja. Segala sesuatu yang tidak {i>mouse<i} diemulasikan, dan pengembang tahu persis apa yang harus diandalkan.

Namun, sederhana tidak selalu berarti baik. Seiring waktu, semakin penting bahwa tidak semuanya (atau berpura-pura menjadi) tikus: Anda bisa pena yang sensitif terhadap tekanan dan yang peka terhadap kemiringan, untuk kebebasan berkreasi yang luar biasa; Anda bisa gunakan jari Anda, jadi yang Anda butuhkan hanyalah perangkat dan tangan Anda; dan hai, kenapa tidak menggunakan lebih dari satu jari saat melakukannya?

Ada peristiwa sentuh untuk sementara waktu membantu kami melakukannya, tetapi API ini adalah API yang sepenuhnya terpisah khususnya untuk sentuhan, memaksa Anda untuk menulis kode dua model peristiwa terpisah jika Anda ingin mendukung {i>mouse<i} dan {i>touch<i}. Chrome 55 dikirimkan dengan standar yang lebih baru yang menyatukan kedua model: peristiwa pointer.

Model peristiwa tunggal

Peristiwa pointer menyatukan model input pointer untuk browser, yang menyatukan sentuhan, pena, dan mouse menjadi satu set peristiwa. Contoh:

document.addEventListener('pointermove',
    ev => console.log('The pointer moved.'));
foo.addEventListener('pointerover',
    ev => console.log('The pointer is now over foo.'));

Berikut adalah daftar semua peristiwa yang tersedia, yang akan terlihat cukup familier jika yang sudah Anda kenali dengan peristiwa {i>mouse<i}:

pointerover Pointer telah memasuki kotak pembatas elemen. Hal ini segera terjadi untuk perangkat yang mendukung pengarahan kursor, atau sebelum Peristiwa pointerdown untuk perangkat yang tidak memilikinya.
pointerenter Serupa dengan pointerover, tetapi tidak menggelembung dan menangani keturunan secara berbeda. Detail tentang spesifikasi.
pointerdown Pointer telah memasuki status tombol aktif, baik dengan sebuah tombol ditekan atau kontak sedang dibuat, tergantung pada semantik perangkat input.
pointermove Pointer telah berubah posisi.
pointerup Pointer telah meninggalkan status tombol aktif.
pointercancel Sesuatu telah terjadi, yang berarti pointer tidak mungkin memunculkan peristiwa lainnya. Ini berarti Anda harus membatalkan tindakan apa pun yang sedang berlangsung dan kembali ke status input netral.
pointerout Pointer telah meninggalkan kotak pembatas elemen atau layar. Juga setelah pointerup, jika perangkat tidak mendukung pengarahan kursor.
pointerleave Serupa dengan pointerout, tetapi tidak menggelembung dan menangani keturunan secara berbeda. Detail tentang spesifikasi.
gotpointercapture Elemen telah menerima tangkapan pointer.
lostpointercapture Pointer yang sedang diambil telah dirilis.

Jenis input yang berbeda

Umumnya, Kejadian Pointer memungkinkan Anda untuk menulis kode dengan cara agnostik input, tanpa perlu mendaftarkan pengendali peristiwa terpisah untuk perangkat input yang berbeda. Tentu saja, Anda masih perlu memperhatikan perbedaan di antara jenis-jenis input, seperti apakah konsep pengarahan kursor. Jika Anda memang ingin membedakan tipe perangkat input yang berbeda – mungkin untuk memberikan kode/fungsi terpisah untuk input yang berbeda – tetapi Anda dapat melakukannya dari dalam pengendali peristiwa yang sama menggunakan properti pointerType dari PointerEvent dalam antarmuka berbasis web yang sederhana. Misalnya, jika Anda melakukan coding panel navigasi samping, Anda bisa memiliki logika berikut di peristiwa pointermove Anda:

switch(ev.pointerType) {
    case 'mouse':
    // Do nothing.
    break;
    case 'touch':
    // Allow drag gesture.
    break;
    case 'pen':
    // Also allow drag gesture.
    break;
    default:
    // Getting an empty string means the browser doesn't know
    // what device type it is. Let's assume mouse and do nothing.
    break;
}

Tindakan default

Pada browser yang mendukung sentuhan, gestur tertentu digunakan untuk membuat halaman men-scroll, memperbesar/memperkecil, atau memuat ulang. Dalam kasus peristiwa sentuh, Anda tetap akan menerima peristiwa saat terjadi tindakan – misalnya, touchmove akan tetap diaktifkan saat pengguna men-scroll.

Dengan peristiwa pointer, setiap kali tindakan default seperti scroll atau zoom dipicu, Anda akan mendapatkan peristiwa pointercancel, untuk memberi tahu bahwa browser telah dijalankan untuk mengontrol pointer. Contoh:

document.addEventListener('pointercancel',
    ev => console.log('Go home, the browser is in charge now.'));

Kecepatan bawaan: Model ini memungkinkan performa yang lebih baik secara default, dibandingkan dengan kejadian sentuh, di mana Anda harus menggunakan pemroses peristiwa pasif untuk mencapai tingkat responsivitas yang sama.

Anda dapat mencegah browser mengambil alih kontrol dengan touch-action Properti CSS. Menetapkannya ke none pada elemen akan menonaktifkan semua tindakan yang ditentukan browser dimulai melalui elemen tersebut. Tetapi ada beberapa nilai lain untuk kontrol yang lebih mendetail, seperti pan-x, guna memungkinkan {i>browser<i} untuk bereaksi terhadap gerakan pada sumbu x tetapi tidak pada sumbu y. Chrome 55 mendukung nilai berikut:

auto Default: browser dapat melakukan tindakan {i>default<i} apa pun.
none Browser tidak diizinkan untuk melakukan tindakan default apa pun.
pan-x Browser hanya diizinkan untuk melakukan tindakan default scroll horizontal.
pan-y Browser hanya diizinkan untuk melakukan tindakan default scroll vertikal.
pan-left Browser hanya diperbolehkan melakukan tindakan {i>default<i} scroll horizontal, dan hanya untuk menggeser halaman ke kiri.
pan-right Browser hanya diperbolehkan melakukan tindakan {i>default<i} scroll horizontal, dan hanya untuk menggeser halaman ke kanan.
pan-up Browser hanya diizinkan untuk melakukan tindakan default scroll vertikal, dan hanya untuk menggeser halaman ke atas.
pan-down Browser hanya diizinkan untuk melakukan tindakan default scroll vertikal, dan hanya untuk menggeser halaman ke bawah.
manipulation Browser hanya diizinkan untuk melakukan tindakan scroll dan zoom.

Rekaman pointer

Pernah kewalahan dalam proses men-debug mouseup yang rusak hingga Anda menyadari bahwa itu karena pengguna melepaskan tombol di luar target klik Anda? Tidak? Oke, mungkin hanya aku saja.

Namun, sampai sekarang tidak ada cara yang sangat bagus untuk mengatasi masalah ini. Tentu, Anda dapat menyiapkan pengendali mouseup pada dokumen, dan menyimpan beberapa status di aplikasi Anda untuk melacak berbagai hal. Itu bukanlah solusi terbersih, meskipun begitu, terutama jika Anda membuat komponen web dan mencoba menjaga agar semua elemen tetap bagus dan terisolasi.

Dengan peristiwa {i>pointer<i} hadir solusi yang jauh lebih baik: Anda dapat menangkap pointer, agar Anda yakin akan mendapatkan peristiwa pointerup tersebut (atau peristiwa lain yang sulit dipahami teman).

const foo = document.querySelector('#foo');
foo.addEventListener('pointerdown', ev => {
    console.log('Button down, capturing!');
    // Every pointer has an ID, which you can read from the event.
    foo.setPointerCapture(ev.pointerId);
});

foo.addEventListener('pointerup', 
    ev => console.log('Button up. Every time!'));

Dukungan browser

Pada saat penulisan, Peristiwa Penunjuk didukung di Internet Explorer 11, Microsoft Edge, Chrome, dan Opera, serta didukung sebagian di Firefox. Anda dapat temukan daftar terbaru di caniuse.com.

Anda dapat menggunakan polyfill Peristiwa Pointer untuk untuk mengisi kesenjangan. Atau, memeriksa dukungan browser saat runtime adalah langsung:

if (window.PointerEvent) {
    // Yay, we can use pointer events!
} else {
    // Back to mouse and touch events, I guess.
}

Peristiwa pointer adalah kandidat yang fantastis untuk {i>progressive enhancement<i}: hanya mengubah metode inisialisasi untuk melakukan pemeriksaan di atas, menambahkan peristiwa pointer di blok if, dan pindahkan pengendali peristiwa mouse/sentuh ke Pemblokiran else.

Jadi silakan, coba mereka dan beri tahu kami pendapat Anda.