Sentuhan dan mouse

Bersama lagi untuk pertama kalinya

Pengantar

Selama hampir tiga puluh tahun, pengalaman komputasi desktop telah berpusat pada keyboard dan mouse atau trackpad sebagai perangkat input pengguna utama kami. Namun, selama satu dekade terakhir, smartphone dan tablet telah menghadirkan paradigma interaksi baru: sentuh. Dengan diperkenalkannya komputer Windows 8 yang berkemampuan sentuh, dan kini dengan dirilisnya Chromebook Pixel berkemampuan sentuh, sentuhan kini menjadi bagian dari pengalaman desktop yang diharapkan. Salah satu tantangan terbesar adalah membangun pengalaman yang tidak hanya berfungsi di perangkat sentuh dan mouse, tetapi juga di perangkat yang memungkinkan pengguna menggunakan kedua metode input tersebut - terkadang secara bersamaan.

Artikel ini akan membantu Anda memahami bagaimana kemampuan sentuh dibangun ke dalam browser, bagaimana Anda dapat mengintegrasikan mekanisme antarmuka baru ini ke dalam aplikasi yang sudah ada, dan bagaimana sentuhan dapat bermain dengan baik dengan input mouse.

Kondisi Sentuhan di Platform Web

iPhone merupakan platform populer pertama yang memiliki API sentuh khusus yang dibangun di dalam browser web. Beberapa vendor browser lain telah membuat antarmuka API serupa yang dibuat agar kompatibel dengan implementasi iOS, yang kini dijelaskan dalam spesifikasi"Peristiwa Sentuh versi 1". Peristiwa sentuh didukung oleh Chrome dan Firefox di desktop, dan oleh Safari di iOS dan Chrome, serta browser Android di Android, serta browser seluler lainnya seperti browser Blackberry.

Kolega saya Boris Smus menulis tutorial HTML5Rocks yang keren tentang peristiwa Sentuhan, yang masih bisa menjadi cara bagus untuk memulai jika Anda belum pernah melihat peristiwa Sentuhan sebelumnya. Bahkan, jika Anda belum pernah menggunakan peristiwa sentuh sebelumnya, baca artikel tersebut sekarang, sebelum melanjutkan. Lanjutkan, saya akan menunggu.

Selesai? Setelah Anda memiliki dasar dasar dalam peristiwa sentuh, tantangan dalam menulis interaksi yang diaktifkan dengan sentuhan adalah bahwa interaksi sentuh bisa sedikit berbeda dengan peristiwa mouse (dan trackpad pengemulasi mouse dan trackball) - dan meskipun antarmuka sentuh biasanya mencoba meniru mouse, emulasi tersebut tidak sempurna atau lengkap; Anda benar-benar perlu bekerja melalui kedua gaya interaksi, dan mungkin harus mendukung setiap antarmuka secara terpisah.

Hal terpenting: Pengguna Mungkin Memiliki Sentuhan dan Mouse

Banyak developer telah membuat situs yang secara statis mendeteksi apakah lingkungan mendukung peristiwa sentuh, lalu membuat asumsi bahwa mereka hanya perlu mendukung peristiwa sentuh (dan bukan mouse). Hal ini sekarang menjadi asumsi yang salah - sebagai gantinya, hanya karena ada peristiwa sentuh, bukan berarti pengguna utamanya menggunakan perangkat input sentuh tersebut. Perangkat seperti Chromebook Pixel dan beberapa laptop Windows 8 kini mendukung metode input Mouse dan Sentuh, dan banyak lagi dalam waktu dekat. Pada perangkat ini, cukup alami bagi pengguna untuk menggunakan mouse dan layar sentuh untuk berinteraksi dengan aplikasi, sehingga "mendukung sentuhan" tidak sama dengan "tidak memerlukan dukungan mouse". Anda tidak bisa menganggap masalah ini sebagai "Saya harus menulis dua gaya interaksi yang berbeda dan beralih di antara keduanya", Anda perlu memikirkan bagaimana kedua interaksi tersebut akan bekerja sama dan juga secara independen. Di Chromebook Pixel saya, saya sering menggunakan trackpad, tetapi saya juga mengambil gambar ke atas dan menyentuh layar - di aplikasi atau halaman yang sama, saya melakukan apa pun yang terasa paling alami pada saat itu. Di sisi lain, beberapa pengguna laptop layar sentuh akan jarang menggunakan layar sentuh sama sekali - sehingga kehadiran input sentuh tidak seharusnya menonaktifkan atau menghambat kontrol mouse.

Sayangnya, sulit untuk mengetahui apakah lingkungan browser pengguna mendukung input sentuh atau tidak; idealnya, browser di komputer desktop akan selalu menunjukkan dukungan untuk peristiwa sentuh sehingga layar sentuh dapat dipasang kapan saja (misalnya, jika layar sentuh yang dipasang melalui KVM tersedia). Karena semua alasan ini, sebaiknya aplikasi Anda tidak beralih antara sentuhan dan mouse - cukup dukung keduanya!

Mendukung Mouse dan Sentuh Bersama

#1 - Mengeklik dan Mengetuk - Urutan Hal "Alam"

Masalah pertama adalah antarmuka sentuh biasanya mencoba mengemulasi klik mouse - tentu saja, karena antarmuka sentuh perlu bekerja pada aplikasi yang hanya berinteraksi dengan peristiwa mouse sebelumnya. Anda dapat menggunakan ini sebagai pintasan - karena peristiwa "klik" akan terus diaktifkan, baik pengguna mengklik dengan mouse atau mengetuk jari mereka pada layar. Namun, ada beberapa masalah dengan pintasan ini.

Pertama, Anda harus berhati-hati saat mendesain interaksi sentuh yang lebih canggih: ketika pengguna menggunakan mouse, ia akan merespons melalui peristiwa klik, tetapi ketika pengguna menyentuh layar, peristiwa sentuh dan klik akan terjadi. Untuk satu klik, urutan peristiwanya adalah:

  1. mulai sentuh
  2. touchmove
  3. touchend
  4. mouseover
  5. mousemove
  6. mousedown
  7. mouse ke atas
  8. click

Ini, tentu saja, berarti bahwa jika Anda memproses peristiwa sentuh seperti touchstart, Anda perlu memastikan bahwa Anda juga tidak memproses peristiwa mousedown dan/atau klik yang sesuai. Jika Anda dapat membatalkan peristiwa sentuh (memanggil preventDefault() di dalam pengendali peristiwa), maka tidak ada peristiwa mouse yang akan dihasilkan untuk sentuhan. Salah satu aturan terpenting pengendali sentuh adalah:

Namun, hal ini juga mencegah perilaku browser default lainnya (seperti scroll) - meskipun biasanya Anda menangani peristiwa sentuh sepenuhnya di pengendali, dan Anda INGIN menonaktifkan tindakan default tersebut. Secara umum, Anda sebaiknya menangani dan membatalkan semua peristiwa sentuh, atau menghindari pengendali untuk peristiwa tersebut.

Kedua, ketika pengguna mengetuk elemen di laman web di perangkat seluler, halaman yang belum dirancang untuk interaksi seluler memiliki penundaan setidaknya 300 milidetik antara peristiwa touchstart dan pemrosesan peristiwa mouse (mousedown). Pengujian ini dapat dilakukan menggunakan Chrome, Anda dapat mengaktifkan "Mengemulasi peristiwa sentuh" di Developer Tools Chrome untuk membantu menguji antarmuka sentuh pada sistem non-sentuh.

Penundaan ini memberi waktu pada browser untuk menentukan apakah pengguna melakukan gestur lain - khususnya, zoom ketuk dua kali. Tentunya, hal ini dapat menjadi masalah jika Anda ingin mendapatkan respons instan terhadap sentuhan jari. Ada pekerjaan yang sedang berlangsung untuk mencoba membatasi skenario yang menyebabkan penundaan ini terjadi secara otomatis.

Chrome untuk Android Browser Android Opera Mobile untuk Android) Firefox untuk Android iOS Safari
Area pandang tidak skalabel Tidak ada penundaan 300 md 300 md Tidak ada penundaan 300 md
Tidak Ada Area Pandang 300 md 300 md 300 md 300 md 300 md

Cara pertama dan termudah untuk menghindari penundaan ini adalah "memberi tahu" browser seluler bahwa halaman Anda tidak perlu diperbesar - yang dapat dilakukan menggunakan area pandang tetap, misalnya dengan memasukkan ke dalam halaman:

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

Tentu saja, ini tidak selalu sesuai - ini menonaktifkan zoom cubit, yang mungkin diperlukan untuk alasan aksesibilitas, jadi gunakan dengan hemat jika ada (jika Anda menonaktifkan penskalaan pengguna, Anda mungkin ingin menyediakan cara lain untuk meningkatkan keterbacaan teks di aplikasi Anda). Selain itu, untuk Chrome di perangkat kelas desktop yang mendukung sentuhan, dan browser lain di platform seluler saat halaman memiliki area pandang yang tidak skalabel, penundaan ini tidak berlaku.

#2: Peristiwa Mousemove Tidak Diaktifkan dengan Sentuhan

Penting untuk dicatat pada tahap ini bahwa emulasi peristiwa mouse dalam antarmuka sentuh biasanya tidak mencakup emulasi peristiwa mousemove - jadi jika Anda membangun kontrol indah berbasis mouse yang menggunakan peristiwa mousemove, kontrol tersebut mungkin tidak akan berfungsi dengan perangkat sentuh kecuali jika Anda secara khusus menambahkan pengendali touchmove juga.

Browser biasanya otomatis menerapkan interaksi yang sesuai untuk interaksi sentuh pada kontrol HTML - jadi, misalnya, Kontrol Rentang HTML5 hanya akan berfungsi saat Anda menggunakan interaksi sentuh. Namun, jika Anda telah menerapkan kontrol Anda sendiri, kontrol tersebut kemungkinan tidak akan berfungsi pada interaksi jenis klik dan seret; pada kenyataannya, beberapa library yang umum digunakan (seperti jQueryUI) belum mendukung interaksi sentuh secara native dengan cara ini (meskipun untuk jQueryUI, ada beberapa perbaikan Monkey-patch untuk masalah ini). Ini adalah salah satu masalah pertama yang saya alami saat mengupgrade aplikasi Web Audio Playground saya agar berfungsi dengan sentuhan - penggeser berbasis jQueryUI, sehingga tidak berfungsi dengan interaksi klik dan tarik. Saya mengubahnya ke HTML5 Range controls, dan semuanya berfungsi. Atau, tentu saja, saya dapat menambahkan pengendali touchmove untuk memperbarui penggeser, tetapi ada satu masalah dengan itu...

#3: Touchmove dan MouseMove Bukan Hal yang Sama

Kesalahan yang sering saya lihat pada beberapa developer adalah ketika melakukan pemanggilan pengendali touchmove dan mousemove ke codepath yang sama. Perilaku peristiwa ini sangat mirip, tetapi sedikit berbeda - khususnya, peristiwa sentuh selalu menargetkan elemen tempat peristiwa sentuh DIMULAI, sedangkan peristiwa mouse menargetkan elemen yang saat ini berada di bawah kursor mouse. Inilah sebabnya kita memiliki peristiwa pengarahan mouse dan mouse, tetapi tidak ada peristiwa touchover dan touchout yang sesuai - hanya touchend.

Cara paling umum untuk menggigit Anda adalah jika Anda kebetulan menghapus (atau memindahkan) elemen yang mulai disentuh pengguna. Misalnya, bayangkan carousel gambar dengan pengendali sentuh di seluruh carousel untuk mendukung perilaku scroll kustom. Saat gambar yang tersedia berubah, Anda menghapus beberapa elemen <img> dan menambahkan yang lainnya. Jika pengguna kebetulan mulai menyentuh salah satu gambar tersebut, lalu Anda menghapusnya, handler Anda (yang ada di ancestor elemen img) hanya akan berhenti menerima peristiwa sentuh (karena mereka dikirim ke target yang tidak lagi berada di pohon) - pengguna akan terlihat seperti pengguna menahan jarinya di satu tempat meskipun pengguna mungkin telah memindahkan dan akhirnya menghapusnya.

Anda tentu saja dapat menghindari masalah ini dengan menghindari menghapus elemen yang memiliki (atau memiliki ancestor yang memiliki) pengendali sentuh saat sentuhan aktif. Sebagai alternatif, daripada mendaftarkan pengendali touchend/touchmove statis, sebaiknya tunggu hingga Anda mendapatkan peristiwa touchstart, lalu tambahkan pengendali touchmove/touchend/touchcancel ke target peristiwa touchstart (dan menghapusnya saat akhir/batal). Dengan demikian, Anda akan terus menerima peristiwa untuk sentuhan meskipun elemen target dipindahkan/dihapus. Anda dapat memainkannya sedikit di sini - sentuh kotak merah dan sambil menahan tombol escape untuk menghapusnya dari DOM.

#4: Sentuh dan :Arahkan kursor

Metafora pointer mouse memisahkan posisi kursor dari pemilihan secara aktif, dan ini memungkinkan developer menggunakan status pengarahan kursor untuk menyembunyikan dan menampilkan informasi yang mungkin terkait dengan pengguna. Namun, sebagian besar antarmuka sentuh saat ini tidak mendeteksi jari yang "mengarahkan kursor" ke target.Jadi, memberikan informasi yang penting secara semantik (mis. memberikan pop-up "apa kontrol ini?") berdasarkan pengarahan kursor tidak boleh dilakukan, kecuali jika Anda juga memberikan cara yang ramah sentuhan untuk mengakses informasi ini. Anda harus berhati-hati tentang cara mengarahkan kursor untuk menyampaikan informasi kepada pengguna.

Namun yang cukup menarik, pseudoclass CSS :hover dapat dipicu oleh antarmuka sentuh dalam beberapa kasus - mengetuk elemen akan membuatnya menjadi :active saat jari berada di bawah, dan juga memperoleh status :hover. (Dengan Internet Explorer, :kursor hanya berlaku saat jari pengguna berada di bawah - browser lain terus menerapkan :kursor hingga ketukan atau gerakan mouse berikutnya.) Ini adalah pendekatan yang baik agar menu pop-out berfungsi pada antarmuka sentuh - efek samping dari membuat elemen aktif adalah status :hover juga diterapkan. Contoh:

<style>
img ~ .content {
  display:none;
}

img:hover ~ .content {
  display:block;
}
</style>

<img src="/awesome.png">
<div class="content">This is an awesome picture of me</div>

Setelah elemen lain diketuk, elemen tersebut tidak lagi aktif, dan status pengarahan kursor menghilang, seolah-olah pengguna menggunakan pointer mouse dan memindahkannya dari elemen. Anda mungkin ingin menggabungkan konten dalam elemen <a> untuk membuatnya juga sebagai tabstop - dengan cara tersebut, pengguna dapat mengalihkan informasi tambahan pada pengarahan kursor atau klik mouse, ketukan sentuh, atau penekanan tombol, tanpa memerlukan JavaScript. Saya terkejut saat mulai mengerjakan Playground Audio Web saya agar berfungsi dengan baik dengan antarmuka sentuh yang menu pop-out berfungsi dengan baik saat disentuh, karena saya telah menggunakan struktur seperti ini.

Metode di atas berfungsi dengan baik untuk antarmuka berbasis pointer mouse, serta untuk antarmuka sentuh. Hal ini berbeda dengan menggunakan atribut "judul" saat kursor diarahkan, yang TIDAK akan muncul saat elemen diaktifkan:

<img src="/awesome.png" title="this doesn't show up in touch">

#5: Presisi Sentuh vs. Mouse

Meskipun mouse memiliki disosiasi konseptual dari kenyataan, ternyata mereka sangat akurat, karena sistem operasi yang mendasarinya umumnya melacak presisi piksel yang tepat untuk kursor. Developer seluler telah belajar bahwa sentuhan jari pada layar sentuh tidak seakurat, terutama karena ukuran area permukaan jari saat bersentuhan dengan layar (dan sebagian karena jari Anda menghalangi layar).

Banyak individu dan perusahaan telah melakukan riset pengguna yang ekstensif tentang cara merancang aplikasi dan situs yang mengakomodasi interaksi berbasis jari, dan banyak buku yang telah ditulis tentang topik tersebut. Saran dasarnya adalah untuk meningkatkan ukuran target sentuh dengan meningkatkan padding, dan mengurangi kemungkinan ketukan yang salah dengan meningkatkan margin antar elemen. (Margin tidak disertakan dalam penanganan deteksi hit terhadap peristiwa sentuh dan klik, sedangkan padding disertakan.) Salah satu perbaikan utama yang harus saya lakukan pada Web Audio Playground adalah meningkatkan ukuran titik koneksi sehingga lebih mudah disentuh secara akurat.

Banyak vendor browser yang menangani antarmuka berbasis sentuh juga telah memperkenalkan logika ke dalam browser untuk membantu menargetkan elemen yang benar saat pengguna menyentuh layar dan mengurangi kemungkinan klik yang salah - meskipun hal ini biasanya hanya mengoreksi peristiwa klik, bukan bergerak (meskipun Internet Explorer tampaknya juga memodifikasi peristiwa mousedown/mousemove/mouseup).

#6: Pastikan Pengendali Sentuhan Tepat atau Mereka Akan Mengganggu Scroll Anda

Penting juga untuk membatasi pengendali sentuh hanya pada elemen tempat Anda membutuhkannya; elemen sentuh dapat memiliki bandwidth yang sangat tinggi, jadi sebaiknya hindari pengendali sentuh pada elemen scroll (karena pemrosesan Anda dapat mengganggu pengoptimalan browser untuk scroll sentuh bebas jank yang cepat - browser modern mencoba men-scroll di thread GPU, tetapi ini tidak mungkin jika mereka harus memeriksa dengan JavaScript terlebih dahulu untuk melihat apakah setiap peristiwa sentuh akan ditangani oleh aplikasi). Anda dapat melihat contoh perilaku ini.

Salah satu panduan yang harus diikuti untuk menghindari masalah ini adalah memastikan bahwa jika Anda hanya menangani peristiwa sentuh di sebagian kecil UI, Anda hanya melampirkan pengendali sentuh di sana (bukan, misalnya, di <body> halaman); singkatnya, batasi cakupan pengendali sentuh Anda sebanyak mungkin.

7. Multisentuh

Tantangan terakhir yang menarik adalah meskipun kami menyebutnya sebagai antarmuka pengguna "Sentuh", hampir secara universal dukungan tersebut sebenarnya untuk Multi-sentuh - yaitu, API menyediakan lebih dari satu input sentuh sekaligus. Saat mulai mendukung sentuhan dalam aplikasi, Anda harus mempertimbangkan bagaimana beberapa sentuhan dapat memengaruhi aplikasi.

Jika Anda membangun aplikasi yang sebagian besar dijalankan dengan mouse, maka Anda terbiasa membangun dengan paling banyak satu titik kursor - sistem biasanya tidak mendukung beberapa kursor mouse. Untuk banyak aplikasi, Anda hanya akan memetakan peristiwa sentuh ke satu antarmuka kursor, tetapi sebagian besar perangkat keras yang telah kita lihat untuk input sentuh desktop dapat menangani setidaknya 2 input simultan, dan sebagian besar hardware baru tampaknya mendukung setidaknya 5 input simultan. Tentu saja, untuk mengembangkan keyboard piano di layar, Anda perlu mendukung beberapa input sentuh secara simultan.

W3C Touch API yang saat ini diterapkan tidak memiliki API untuk menentukan berapa banyak titik sentuh yang didukung perangkat keras, jadi Anda harus menggunakan perkiraan terbaik untuk mengetahui berapa banyak titik sentuh yang diinginkan pengguna - atau, tentu saja, memperhatikan berapa banyak titik sentuh yang Anda lihat dalam praktik dan beradaptasi. Misalnya, dalam aplikasi piano, jika tidak melihat lebih dari dua titik sentuh, Anda dapat menambahkan beberapa UI "akor". PointerEvents API memiliki API untuk menentukan kemampuan perangkat.

Menyempurnakan

Semoga artikel ini memberi Anda beberapa panduan tentang tantangan umum dalam menerapkan sentuhan bersama interaksi mouse. Yang lebih penting daripada saran lainnya, tentu saja, adalah Anda perlu menguji aplikasi di seluler, tablet, serta lingkungan desktop mouse dan sentuh yang dikombinasikan. Jika Anda tidak memiliki hardware sentuh+mouse, gunakan "Emulasikan peristiwa sentuh" Chrome untuk membantu Anda menguji berbagai skenario.

Mengikuti panduan ini tidak hanya dapat dilakukan, tetapi relatif mudah, untuk membuat pengalaman interaktif menarik yang berfungsi baik dengan input sentuh, input mouse, dan bahkan kedua gaya interaksi secara bersamaan.