Menghindari paint sangat penting untuk mencapai kecepatan frame yang halus, terutama di perangkat seluler. Namun, terkadang cat muncul di tempat yang paling tidak biasa. Artikel ini membahas mengapa GIF animasi dapat menyebabkan paint yang tidak perlu terjadi, dan perbaikan yang sangat sederhana yang dapat Anda terapkan.
Lapisan keceriaan
Seperti yang mungkin telah Anda ketahui, browser modern mungkin menggambar kumpulan elemen DOM ke dalam "gambar" yang terpisah, yang disebut lapisan. Terkadang ada satu lapisan untuk seluruh laman, kadang-kadang ada ratusan, atau dalam kasus yang jarang terjadi - ribuan!
Ketika elemen DOM dikelompokkan bersama ke dalam lapisan dan salah satu elemen berubah secara visual, kita akhirnya harus menggambar tidak hanya elemen yang diubah, tetapi juga semua elemen lain di lapisan yang tumpang-tindih dengan elemen yang diubah tersebut. Mengecat satu hal di atas hal lain akan mengakibatkan piksel yang ditimpa secara efektif "hilang" selamanya; jika Anda ingin piksel asli kembali, Anda perlu menggambar ulang.
Oleh karena itu, terkadang kita ingin mengisolasi satu elemen dari elemen lainnya sehingga saat digambar, kita tidak perlu menggambar ulang elemen lain yang belum berubah. Misalnya, saat Anda menggabungkan header halaman tetap dengan konten yang dapat di-scroll, Anda harus melukis ulang header setiap kali konten di-scroll, serta konten yang baru terlihat. Dengan menempatkan header di lapisan terpisah, browser dapat mengoptimalkan scroll. Saat Anda men-scroll, browser dapat memindahkan lapisan - mungkin dengan bantuan GPU - dan menghindari mengecat ulang salah satu lapisan.
Setiap lapisan tambahan meningkatkan konsumsi memori dan menambah overhead performa, sehingga tujuannya adalah mengelompokkan halaman menjadi sesedikit mungkin lapisan sekaligus mempertahankan performa yang baik.
Apa hubungannya dengan GIF animasi?
Baiklah, mari kita lihat gambar ini:
Ini adalah penyiapan lapisan potensial untuk aplikasi sederhana. Di sini ada empat lapisan: tiga di antaranya (lapisan 2 hingga 4) adalah elemen antarmuka; lapisan belakang adalah loader, yang kebetulan berupa GIF animasi. Dalam alur normal Anda menampilkan loader (lapisan 1) saat aplikasi dimuat, kemudian setelah semua selesai Anda akan menampilkan lapisan lainnya. Namun, inilah kuncinya: Anda perlu menyembunyikan animasi GIF.
Tapi kenapa aku harus menyembunyikannya?!
Pertanyaan bagus. Sebenarnya, browser hanya akan memeriksa visibilitas GIF dan menghindari menggambar secara otomatis. Sayangnya, memeriksa apakah GIF animasi terhalang atau terlihat di layar biasanya lebih mahal daripada sekadar melukisnya, sehingga akan digambar.
Dalam kasus terbaik, GIF berada dalam lapisannya sendiri dan browser hanya perlu menggambar dan menguploadnya ke GPU. Namun dalam kasus terburuk, semua elemen Anda mungkin dikelompokkan ke dalam satu lapisan dan browser harus melakukan penggambaran ulang setiap elemen tunggal. Setelah selesai, GPU masih perlu mengupload semuanya ke GPU. Semua ini bekerja untuk setiap {i>frame<i} GIF, terlepas dari kenyataan bahwa pengguna bahkan tidak dapat melihat GIF.
Di desktop, Anda mungkin bisa menghindari perilaku pengecatan semacam ini karena CPU dan GPU lebih kuat, dan ada banyak bandwidth untuk mentransfer data di antara keduanya. Namun, di perangkat seluler, biaya menggambar sangat mahal sehingga Anda harus sangat berhati-hati.
Browser apa yang terpengaruh?
Seperti yang sering terjadi, perilaku setiap browser berbeda. Kini Chrome, Safari, dan Opera semuanya melakukan repaint, meskipun GIF dikaburkan. Di sisi lain, Firefox mengetahui bahwa GIF terhalang dan tidak perlu digambar ulang. Internet Explorer tetap menjadi kotak hitam, dan bahkan di IE11 - karena alat F12 masih dikembangkan - tidak ada indikasi apakah pengecatan ulang sedang berlangsung atau tidak.
Bagaimana cara mengetahui apakah saya memiliki masalah ini?
Cara termudah adalah menggunakan "Show paint persegi panjang" di Chrome DevTools. Muat DevTools dan tekan roda gigi di sudut kanan bawah (), lalu pilih Show paint rectangles di bagian Rendering.
Sekarang yang perlu Anda lakukan adalah mencari persegi panjang merah seperti ini:
Kotak merah kecil di layar menunjukkan bahwa Chrome sedang mengecat ulang sesuatu. Anda tahu bahwa ada GIF loader yang tersembunyi di balik elemen lainnya, jadi ketika Anda melihat kotak merah seperti ini, Anda harus menyembunyikan elemen yang terlihat dan memeriksa apakah Anda telah membiarkan GIF animasi berputar. Jika sudah, Anda perlu memunculkan beberapa CSS atau JavaScript untuk menerapkan display: none
atau visibility: hidden
ke elemen tersebut atau elemen induknya. Tentu saja jika itu hanya gambar latar, pastikan Anda menghapusnya.
Jika Anda ingin melihat contoh perilaku ini di situs live, lihat Allegro, dengan gambar setiap produk memiliki GIF loader yang dikaburkan, bukan tersembunyi secara eksplisit.
Kesimpulan
Untuk mencapai 60 fps, Anda hanya melakukan hal yang diperlukan untuk merender halaman, tidak lebih. Menghapus kelebihan cat adalah langkah penting untuk mencapai sasaran ini. GIF animasi yang dibiarkan berjalan dapat memicu paint yang tidak perlu, sesuatu yang dapat Anda temukan dan debug dengan mudah menggunakan alat Show paint persegi panjang pada DevTools.
Sekarang, Anda tidak membiarkan GIF animasi loader anak kucing berjalan selamanya, bukan?