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: sentuhan. Dengan diperkenalkannya komputer Windows 8 yang mendukung sentuhan, dan sekarang dengan dirilisnya Chromebook Pixel yang mendukung sentuhan, layar sentuh sekarang menjadi bagian dari pengalaman desktop yang diharapkan. Salah satu tantangan terbesar adalah membangun pengalaman yang tidak hanya berfungsi pada perangkat sentuh dan mouse, tetapi juga pada perangkat ini tempat pengguna akan menggunakan kedua metode input - terkadang secara bersamaan.

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

Tingkat Informasi dalam Platform Web

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

Kolega saya Boris Smus menulis tutorial HTML5Rocks tentang peristiwa Touch yang hebat. Itu adalah cara yang bagus untuk memulai jika Anda belum pernah melihat peristiwa Touch sebelumnya. Bahkan, jika Anda belum pernah menggunakan peristiwa sentuh sebelumnya, baca artikel itu sekarang, sebelum melanjutkan. Lanjutkan, saya akan menunggu.

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

Yang Paling Penting: Pengguna Mungkin Memiliki Sentuhan dan Mouse

Banyak developer telah membuat situs yang secara statis mendeteksi apakah suatu lingkungan mendukung peristiwa sentuh, dan kemudian membuat asumsi bahwa mereka hanya perlu mendukung peristiwa sentuh (dan bukan mouse). Sekarang ini asumsi yang salah - sebaliknya, hanya karena ada peristiwa sentuh, bukan berarti pengguna terutama menggunakan perangkat input sentuh tersebut. Perangkat seperti Chromebook Pixel dan beberapa laptop Windows 8 kini mendukung KEDUA metode input Mouse dan Sentuh. Beberapa perangkat lainnya akan segera mendukungnya. Pada perangkat ini, wajar jika pengguna menggunakan mouse dan layar sentuh untuk berinteraksi dengan aplikasi, sehingga "mendukung sentuhan" tidak sama dengan "tidak memerlukan dukungan mouse". Anda tidak dapat menganggap masalahnya sebagai "Saya harus menulis dua gaya interaksi yang berbeda dan beralih di antaranya", Anda perlu memikirkan bagaimana kedua interaksi tersebut akan berfungsi bersama serta secara mandiri. Di Chromebook Pixel, saya sering menggunakan trackpad, tetapi saya juga mengulurkan tangan dan menyentuh layar - pada aplikasi atau halaman yang sama, saya melakukan apa pun yang terasa paling alami saat ini. Di sisi lain, beberapa pengguna laptop layar sentuh akan jarang menggunakan layar sentuh sama sekali - jadi kehadiran input sentuh seharusnya tidak 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 (mis. jika layar sentuh yang terpasang melalui KVM tersedia). Untuk semua alasan ini, aplikasi Anda tidak boleh mencoba beralih antara sentuhan dan mouse - cukup dukung keduanya.

Mendukung Mouse dan Sentuhan Bersama

#1 - Mengklik 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 sebelumnya hanya berinteraksi dengan peristiwa mouse. Anda dapat menggunakan ini sebagai pintasan - karena peristiwa "klik" akan terus diaktifkan, baik pengguna mengklik dengan mouse maupun mengetuk jari mereka di layar. Namun, ada beberapa masalah dengan pintasan ini.

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

  1. mulai sentuh
  2. gerakan sentuh
  3. {i>touchend<i}
  4. mouseover
  5. mousemove
  6. mousedown
  7. gerakan mouse
  8. click

Tentu saja, hal ini berarti bahwa jika Anda memproses peristiwa sentuh seperti touchstart, Anda perlu memastikan bahwa Anda tidak memproses mousedown dan/atau peristiwa klik yang terkait. Jika Anda dapat membatalkan peristiwa sentuh (memanggil preventDefault() di dalam pengendali peristiwa), tidak ada peristiwa mouse yang akan dihasilkan untuk sentuhan. Salah satu aturan yang paling penting dari pengendali sentuh adalah:

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

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

Penundaan ini memungkinkan browser menentukan apakah pengguna melakukan gestur lain - khususnya, ketuk dua kali untuk memperbesar. Tentu saja, hal ini dapat menimbulkan masalah jika Anda ingin mendapatkan respons instan terhadap sentuhan jari. Ada upaya 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 yang 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 dengan "memberi tahu" browser seluler bahwa halaman Anda tidak memerlukan zoom - yang dapat dilakukan menggunakan area pandang tetap, misalnya dengan memasukkan ke halaman Anda:

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

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

#2: Peristiwa Mousemove Tidak Diaktifkan dengan Sentuhan

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

Browser biasanya secara 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 mengimplementasikan kontrol sendiri, mereka kemungkinan tidak akan berfungsi pada interaksi jenis klik-dan-seret; pada kenyataannya, beberapa library yang umum digunakan (seperti jQueryUI) belum mendukung interaksi sentuh 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 kontrol Rentang HTML5, dan cara itu berhasil. Sebagai alternatif, tentu saja, saya bisa saja menambahkan pengendali touchmove untuk memperbarui penggeser, tetapi ada satu masalah dengan itu...

#3: Touchmove dan MouseMove Bukan Hal yang Sama

Kesalahan yang saya lihat pada beberapa developer adalah ketika pengendali {i>touchmove<i} dan {i>mousemove<i} memanggil {i>codepath<i} yang sama. Perilaku peristiwa ini sangat mirip, tetapi sedikit berbeda - khususnya, peristiwa sentuh selalu menargetkan elemen tempat sentuhan STARTED, sementara peristiwa mouse menargetkan elemen yang saat ini berada di bawah kursor mouse. Inilah sebabnya kita memiliki peristiwa pengarahan mouse dan mouseout, tetapi tidak ada peristiwa sentuh dan sentuh yang sesuai - hanya sentuhend.

Cara paling umum hal ini dapat mengganggu 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 akan menghapus beberapa elemen <img> dan menambahkan yang lainnya. Jika pengguna kebetulan mulai menyentuh salah satu gambar tersebut dan kemudian Anda menghapusnya, handler Anda (yang ada pada ancestor elemen img) hanya akan berhenti menerima peristiwa sentuh (karena dikirim ke target yang tidak lagi ada di pohon) - akan terlihat seperti pengguna memegang jari mereka di satu tempat meskipun mereka mungkin telah berpindah dan akhirnya menghapusnya.

Tentu saja Anda dapat menghindari masalah ini dengan menghindari penghapusan elemen yang memiliki (atau memiliki ancestor yang memiliki) pengendali sentuh saat sentuhan aktif. Sebagai alternatif, panduan terbaik adalah daripada mendaftarkan pengendali touchend/touchmove statis, tunggu hingga Anda mendapatkan peristiwa touchstart, lalu menambahkan pengendali touchmove/touchend/touchcancel ke target peristiwa touchstart (dan menghapusnya pada akhir/pembatalan). Dengan cara ini, Anda akan terus menerima peristiwa untuk sentuhan meskipun elemen target dipindahkan/dihapus. Anda dapat bermain dengan tombol ini di sini - sentuh kotak merah dan tahan 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 relevan dengan pengguna. Namun, sebagian besar antarmuka sentuh saat ini tidak mendeteksi jari "mengarahkan kursor" ke target - jadi memberikan informasi yang penting secara semantik (mis. memberikan pop-up "apa kontrol ini?") berdasarkan pengarahan kursor adalah tindakan yang dilarang, kecuali jika Anda juga memberikan cara yang mudah disentuh untuk mengakses informasi ini. Anda harus berhati-hati saat menggunakan pengarahan kursor untuk menyampaikan informasi kepada pengguna.

Meskipun cukup menarik, dalam beberapa kasus CSS :hover pseudoclass CAN dipicu oleh antarmuka sentuh - mengetuk elemen akan membuatnya :aktif saat jari turun, dan juga memperoleh status :hover. (Dengan Internet Explorer, :hover hanya berlaku saat jari pengguna turun - browser lain tetap menggunakan :hover hingga ketukan atau mouse bergerak berikutnya.) Ini adalah pendekatan yang baik agar menu pop-out berfungsi pada antarmuka sentuh - efek samping mengaktifkan elemen 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 arahkan kursor menghilang, seolah-olah pengguna sedang menggunakan kursor mouse dan memindahkannya dari elemen. Anda mungkin ingin menggabungkan konten dalam elemen <a> untuk menjadikannya tabstop juga - dengan begitu pengguna dapat beralih informasi tambahan dengan mengarahkan kursor atau mengklik mouse, ketukan sentuh, atau penekanan tombol, tanpa memerlukan JavaScript. Saya terkejut sekaligus gembira ketika mulai membuat Web Audio Playground bisa berfungsi dengan baik dengan antarmuka sentuh yang menu pop-outnya sudah bekerja dengan baik saat disentuh, karena saya menggunakan struktur semacam ini!

Metode di atas berfungsi dengan baik untuk antarmuka berbasis pointer mouse, serta antarmuka sentuh. Berbeda dengan menggunakan atribut "title" saat mengarahkan kursor, 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 pemisahan konseptual dari kenyataan, ternyata mouse tersebut sangat akurat, karena sistem operasi yang mendasarinya umumnya melacak presisi piksel yang tepat untuk kursor. Di sisi lain, developer seluler telah mengetahui bahwa sentuhan jari pada layar sentuh tidak terlalu akurat, 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 telah ditulis tentang topik tersebut. Saran dasarnya adalah tingkatkan ukuran target sentuh dengan meningkatkan padding, dan mengurangi kemungkinan kesalahan ketuk dengan meningkatkan margin antar elemen. (Margin tidak disertakan dalam penanganan deteksi hit untuk peristiwa sentuh dan klik, sedangkan padding disertakan.) Salah satu perbaikan utama yang harus saya lakukan pada Web Audio Playground adalah menambah ukuran titik koneksi sehingga lebih mudah disentuh 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 ini biasanya hanya mengoreksi peristiwa klik, bukan bergerak (meskipun Internet Explorer tampaknya juga mengubah peristiwa mousedown/mousemove/mouseup).

#6: Jangan Batasi Sentuhan pada Pengendali, atau Akan Mengganggu Scroll Anda

Penting juga untuk menjaga pengendali sentuh hanya terbatas pada elemen di mana Anda membutuhkannya; elemen sentuh bisa memiliki bandwidth yang sangat tinggi, jadi penting untuk menghindari pengendali sentuh pada elemen scroll (karena pemrosesan Anda dapat mengganggu pengoptimalan browser untuk scroll sentuh bebas jank yang cepat - browser modern mencoba men-scroll pada 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: Multi-sentuh

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

Jika Anda membangun aplikasi yang utamanya digerakkan oleh mouse, maka Anda sudah 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 antarmuka kursor tunggal, tetapi sebagian besar hardware 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. Untuk mengembangkan keyboard piano di layar, Anda tentu ingin dapat mendukung beberapa input sentuh simultan.

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

Memperbaiki

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

Tidak hanya mungkin, tetapi juga cukup mudah mengikuti petunjuk ini, untuk membangun pengalaman interaktif menarik yang bekerja baik dengan input sentuh, input mouse, dan bahkan kedua gaya interaksi pada saat yang sama.