Peristiwa input yang disejajarkan

Dave Tapuska
Dave Tapuska

TL;DR (Ringkasan)

  • Chrome 60 mengurangi jank dengan menurunkan frekuensi peristiwa sehingga meningkatkan konsistensi waktu render frame.
  • Metode getCoalescedEvents() yang diperkenalkan di Chrome 58 memberikan kekayaan informasi peristiwa yang sama seperti yang Anda miliki selama ini.

Memberikan pengalaman pengguna yang lancar adalah hal penting untuk web. Waktu antara menerima peristiwa input dan saat visual benar-benar diperbarui, itu penting dan umumnya melakukan lebih sedikit pekerjaan itu penting. Selama beberapa rilis Chrome terakhir, kami telah menurunkan latensi input di semua perangkat ini.

Demi kelancaran dan performa, di Chrome 60, kami membuat perubahan yang menyebabkan peristiwa ini terjadi pada frekuensi yang lebih rendah sekaligus meningkatkan tingkat perincian informasi yang diberikan. Sama seperti saat Jelly Bean dirilis dan menghadirkan Koreografer yang menyelaraskan input di Android, kami menghadirkan input yang selaras dengan frame ke web di semua platform.

Namun, terkadang Anda membutuhkan lebih banyak peristiwa. Jadi, di Chrome 58, kami mengimplementasikan metode yang disebut getCoalescedEvents(), yang memungkinkan aplikasi Anda mengambil jalur lengkap pointer meskipun menerima lebih sedikit peristiwa.

Mari kita bahas tentang frekuensi peristiwa terlebih dahulu.

Menurunkan frekuensi peristiwa

Mari kita pahami beberapa hal dasar: layar sentuh mengirimkan input pada 60-120 Hz dan mouse mengirimkan input biasanya pada 100 Hz (tetapi bisa di mana saja hingga 2000 Hz). Namun, kecepatan refresh standar monitor adalah 60 Hz. Jadi, apa artinya? Artinya, kita menerima input pada kecepatan yang lebih tinggi dari kecepatan pembaruan tampilan yang sebenarnya. Jadi, mari kita lihat linimasa performa dari devtools untuk aplikasi melukis kanvas sederhana.

Pada gambar di bawah, saat input yang diselaraskan dengan requestAnimationFrame() dinonaktifkan, Anda dapat melihat beberapa blok pemrosesan per frame dengan waktu render frame yang tidak konsisten. Blok kuning kecil menunjukkan hit testing untuk hal-hal seperti target peristiwa DOM, mengirim peristiwa, menjalankan JavaScript, mengupdate node yang ditunjuk dan mungkin menghitung ulang tata letak dan gaya.

Linimasa performa yang menunjukkan waktu render frame yang tidak konsisten

Jadi mengapa kita melakukan pekerjaan tambahan yang tidak menimbulkan pembaruan visual apa pun? Idealnya, kita tidak ingin melakukan pekerjaan apa pun yang pada akhirnya tidak menguntungkan pengguna. Mulai Chrome 60, pipeline input akan menunda pengiriman peristiwa berkelanjutan (wheel, mousewheel, touchmove, pointermove, mousemove) dan mengirimkannya tepat sebelum callback requestAnimationFrame() terjadi. Pada gambar di bawah (dengan fitur yang diaktifkan), Anda akan melihat waktu render frame yang lebih konsisten dan lebih sedikit waktu pemrosesan peristiwa.

Kami telah menjalankan eksperimen dengan fitur ini yang diaktifkan di saluran Canary dan Dev dan menemukan bahwa kami melakukan pengujian hit 35% lebih sedikit, yang memungkinkan thread utama siap dijalankan lebih sering.

Catatan penting yang harus diperhatikan oleh developer web adalah setiap peristiwa terpisah (seperti keydown, keyup, mouseup, mousedown, touchstart, touchend) yang terjadi akan segera dikirim bersama dengan peristiwa yang tertunda, dengan mempertahankan urutan relatif. Dengan mengaktifkan fitur ini, banyak pekerjaan yang disederhanakan ke dalam alur loop peristiwa normal, yang memberikan interval input yang konsisten. Hal ini menghadirkan peristiwa berkelanjutan secara inline dengan peristiwa scroll dan resize yang telah disederhanakan ke dalam alur loop peristiwa di Chrome.

Linimasa performa yang menunjukkan waktu render frame yang relatif konsisten.

Kami mendapati bahwa sebagian besar aplikasi yang menggunakan peristiwa semacam itu tidak berguna untuk frekuensi yang lebih tinggi. Android telah menyelaraskan peristiwa selama beberapa tahun, sehingga tidak ada peristiwa baru yang muncul, tetapi situs mungkin mengalami peristiwa yang kurang terperinci di platform desktop. Selalu ada masalah dengan thread utama yang tersendat yang menyebabkan gangguan untuk kelancaran input. Artinya, Anda mungkin melihat lompatan posisi setiap kali aplikasi sedang melakukan pekerjaan, sehingga tidak mungkin untuk mengetahui bagaimana pointer berpindah dari satu titik ke titik lainnya.

Metode getCoalescedEvents()

Seperti yang saya katakan, ada skenario langka saat aplikasi lebih suka mengetahui jalur lengkap pointer. Jadi, untuk memperbaiki kasus ketika Anda melihat lompatan besar dan berkurang frekuensi peristiwa, di Chrome 58, kami meluncurkan ekstensi ke peristiwa pointer yang disebut getCoalescedEvents(). Dan di bawah ini adalah contoh bagaimana jank di thread utama disembunyikan dari aplikasi jika Anda menggunakan API ini.

Membandingkan peristiwa standar dan gabungan.

Daripada menerima satu peristiwa, Anda dapat mengakses array peristiwa historis yang menyebabkan peristiwa tersebut. Android, iOS, dan Windows semua memiliki API yang sangat mirip di SDK native-nya dan kami mengekspos API yang serupa ke web.

Biasanya aplikasi menggambar dapat menggambar titik dengan melihat offset pada peristiwa:

window.addEventListener("pointermove", function(event) {
    drawPoint(event.pageX, event.pageY);
});

Kode ini dapat dengan mudah diubah untuk menggunakan array peristiwa:

window.addEventListener("pointermove", function(event) {
    var events = 'getCoalescedEvents' in event ? event.getCoalescedEvents() : [event];
    for (let e of events) {
    drawPoint(e.pageX, e.pageY);
    }
});

Perhatikan bahwa tidak semua properti pada peristiwa yang digabungkan diisi. Karena peristiwa gabungan tidak benar-benar dikirim, tetapi hanya digunakan untuk perjalanan, peristiwa tersebut tidak diuji. Beberapa kolom seperti currentTarget dan eventPhase akan memiliki nilai defaultnya. Memanggil metode terkait pengiriman seperti stopPropagation() atau preventDefault() tidak akan berpengaruh pada peristiwa induk.