Pemburaman adalah cara yang efektif untuk mengalihkan fokus pengguna. Membuat beberapa elemen visual tampak buram, sementara elemen lainnya tetap fokus, secara alami mengarahkan fokus pengguna. Pengguna mengabaikan konten yang diburamkan dan berfokus pada konten yang dapat mereka baca. Salah satu contohnya adalah daftar ikon yang menampilkan detail tentang setiap item saat kursor diarahkan ke item tersebut. Selama waktu tersebut, pilihan yang tersisa dapat dikaburkan untuk mengalihkan pengguna ke informasi yang baru ditampilkan.
TL;DR
Menganimasikan blur bukanlah pilihan yang baik karena sangat lambat. Sebagai gantinya, hitung terlebih dahulu serangkaian versi yang semakin buram dan lakukan cross-fade di antara versi tersebut. Rekan saya, Yi Gu, menulis library untuk menangani semuanya untuk Anda. Lihat demo kami.
Namun, teknik ini dapat cukup mengganggu jika diterapkan tanpa periode transisi. Menganimasikan blur — bertransisi dari tidak blur ke blur — tampaknya merupakan pilihan yang wajar, tetapi jika Anda pernah mencoba melakukannya di web, Anda mungkin mendapati bahwa animasinya tidak lancar, seperti yang ditunjukkan oleh demo ini jika Anda tidak memiliki mesin yang canggih. Bisakah kita melakukan yang lebih baik?
Permasalahan

Saat ini, kami tidak dapat membuat animasi blur berfungsi secara efisien. Namun, kita dapat menemukan solusi yang terlihat cukup baik, tetapi secara teknis, bukan blur animasi. Untuk memulai, mari kita pahami terlebih dahulu mengapa blur animasi berjalan lambat. Untuk mengaburkan elemen di web, ada dua teknik: Properti CSS filter
dan filter SVG. Berkat peningkatan dukungan dan kemudahan penggunaan, filter CSS biasanya digunakan. Sayangnya, jika Anda harus mendukung Internet Explorer, Anda tidak punya pilihan selain menggunakan filter SVG karena IE 10 dan 11 mendukungnya, tetapi tidak mendukung filter CSS. Kabar baiknya, solusi kami untuk menganimasikan blur berfungsi dengan kedua teknik tersebut. Jadi, mari kita coba menemukan hambatan dengan melihat DevTools.
Jika Anda mengaktifkan "Paint Flashing" di DevTools, Anda tidak akan melihat kilatan sama sekali. Sepertinya tidak ada pengecatan ulang yang terjadi. Dan itu secara teknis benar karena "pengecatan ulang" mengacu pada CPU yang harus mengecat ulang tekstur elemen yang dipromosikan. Setiap kali elemen dipromosikan dan dikaburkan, efek buram diterapkan oleh GPU menggunakan shader.
Filter SVG dan filter CSS menggunakan filter konvolusi untuk menerapkan blur. Filter konvolusi cukup mahal karena untuk setiap piksel output, sejumlah piksel input harus dipertimbangkan. Semakin besar gambar atau semakin besar radius blur, semakin mahal efeknya.
Di sinilah letak masalahnya, kita menjalankan operasi GPU yang cukup mahal setiap frame, yang melebihi anggaran frame 16 md dan oleh karena itu, menghasilkan frame di bawah 60 fps.
Masuk ke dalam labirin
Jadi, apa yang dapat kita lakukan untuk memastikan proses ini berjalan lancar? Kita bisa menggunakan sulap! Alih-alih menganimasikan nilai blur sebenarnya (radius blur), kita melakukan pra-komputasi beberapa salinan yang diblur dengan nilai blur yang meningkat secara eksponensial, lalu melakukan cross-fade di antara salinan tersebut menggunakan opacity
.
Cross-fade adalah serangkaian fade-in dan fade-out opasitas yang tumpang-tindih. Misalnya, jika kita memiliki empat tahap blur, kita akan memudarkan tahap pertama sambil memudarkan tahap kedua secara bersamaan. Setelah tahap kedua mencapai keburaman 100% dan tahap pertama mencapai 0%, kita memudarkan tahap kedua sambil memunculkan tahap ketiga. Setelah selesai, kita akan memudarkan tahap ketiga dan memunculkan versi keempat dan terakhir. Dalam skenario ini, setiap tahap akan memerlukan ¼ dari total durasi yang diinginkan. Secara visual, ini terlihat sangat mirip dengan blur animasi yang nyata.
Dalam eksperimen kami, peningkatan radius blur secara eksponensial per tahap menghasilkan hasil visual terbaik. Contoh: Jika kita memiliki empat tahap blur, kita akan menerapkan
filter: blur(2^n)
ke setiap tahap, yaitu tahap 0: 1 px, tahap 1: 2 px, tahap 2: 4 px
dan tahap 3: 8 px. Jika kita memaksakan setiap salinan yang diburamkan ini ke lapisannya sendiri
(disebut "mempromosikan") menggunakan will-change: transform
, mengubah keburaman pada elemen ini
akan sangat cepat. Secara teori, hal ini akan memungkinkan kita untuk
memuat di awal pekerjaan yang mahal untuk mengaburkan. Ternyata, logikanya salah. Jika
Anda menjalankan demo ini,
Anda akan melihat bahwa kecepatan frame masih di bawah 60 fps, dan efek buramnya justru
lebih buruk daripada sebelumnya.

Pemeriksaan cepat di DevTools mengungkapkan bahwa GPU masih sangat sibuk dan meregangkan setiap frame hingga ~90 md. Tapi kenapa? Kita tidak lagi mengubah nilai blur, hanya opasitas, jadi apa yang terjadi? Masalahnya terletak, sekali lagi, pada sifat efek blur: Seperti yang dijelaskan sebelumnya, jika elemen dipromosikan dan diblur, efek akan diterapkan oleh GPU. Jadi, meskipun kita tidak lagi menganimasikan nilai blur, teksturnya sendiri masih tidak diblur dan perlu diblur ulang setiap frame oleh GPU. Alasan frame rate menjadi lebih buruk dari sebelumnya berasal dari fakta bahwa dibandingkan dengan penerapan naif, GPU sebenarnya memiliki lebih banyak pekerjaan daripada sebelumnya, karena sebagian besar waktu dua tekstur terlihat yang perlu diburamkan secara terpisah.
Hasilnya memang tidak bagus, tetapi membuat animasi berjalan sangat cepat. Kita kembali ke tidak mempromosikan elemen yang akan diburamkan, tetapi mempromosikan wrapper induk. Jika elemen dikaburkan dan dipromosikan, efeknya akan diterapkan oleh GPU. Inilah yang membuat demo kita lambat. Jika elemen dikaburkan, tetapi tidak dipromosikan, pengaburan akan di-rasterisasi ke tekstur induk terdekat. Dalam kasus ini, elemen wrapper induk yang dipromosikan. Gambar yang diburamkan kini menjadi tekstur elemen induk dan dapat digunakan kembali untuk semua frame mendatang. Hal ini hanya berfungsi karena kita tahu bahwa elemen yang diburamkan tidak dianimasikan dan melakukan caching pada elemen tersebut sebenarnya bermanfaat. Berikut demo yang menerapkan teknik ini. Saya penasaran apa pendapat Moto G4 tentang pendekatan ini? Peringatan spoiler: dia menganggap dirinya hebat:

Sekarang kita memiliki banyak ruang kosong di GPU dan 60 fps yang sangat lancar. Kita berhasil!
Menjadikan siap produksi
Dalam demo kami, kami menduplikasi struktur DOM beberapa kali untuk memiliki salinan konten yang akan diburamkan dengan intensitas yang berbeda. Anda mungkin bertanya-tanya bagaimana cara kerjanya di lingkungan produksi karena hal itu mungkin memiliki beberapa efek samping yang tidak diinginkan dengan gaya CSS penulis atau bahkan JavaScript-nya. Anda benar. Masukkan Shadow DOM.
Meskipun sebagian besar orang menganggap Shadow DOM sebagai cara untuk melampirkan elemen "internal"
ke Elemen Khusus mereka, Shadow DOM juga merupakan
primitif isolasi dan performa. JavaScript dan CSS tidak dapat menembus batas Shadow DOM, sehingga kami dapat menduplikasi konten tanpa mengganggu gaya atau logika aplikasi developer. Kita sudah memiliki elemen <div>
untuk
setiap salinan yang akan di-rasterisasi dan sekarang menggunakan <div>
ini sebagai host bayangan. Kita
membuat ShadowRoot
menggunakan attachShadow({mode: 'closed'})
dan melampirkan salinan
konten ke ShadowRoot
, bukan <div>
itu sendiri. Kita juga harus memastikan untuk menyalin semua stylesheet ke dalam ShadowRoot
untuk menjamin bahwa salinan kita memiliki gaya yang sama dengan aslinya.
Beberapa browser tidak mendukung Shadow DOM v1, dan untuk browser tersebut, kita kembali ke hanya menduplikasi konten dan berharap tidak ada yang rusak. Kita dapat menggunakan polyfill Shadow DOM dengan ShadyCSS, tetapi kita tidak menerapkan hal ini di library kita.
Selesai. Setelah mempelajari pipeline rendering Chrome, kita mengetahui cara menganimasikan blur secara efisien di seluruh browser.
Kesimpulan
Efek semacam ini tidak boleh digunakan sembarangan. Karena kita menyalin elemen DOM dan memaksanya ke lapisannya sendiri, kita dapat mendorong batas perangkat kelas bawah. Menyalin semua stylesheet ke setiap ShadowRoot
juga berpotensi
menimbulkan risiko performa, jadi Anda harus memutuskan apakah Anda lebih suka menyesuaikan
logika dan gaya agar tidak terpengaruh oleh salinan di LightDOM
atau menggunakan
teknik ShadowDOM
kami. Namun, terkadang teknik kami mungkin merupakan investasi yang berharga. Lihat kode di repositori GitHub kami
serta
demo dan
hubungi kami di Twitter jika ada pertanyaan.