Animasi Web - element.animate() kini ada di Chrome 36

Budi Budiman
Brendan Kenny

Animasi di web dulunya merupakan provinsi JavaScript, tetapi saat dunia beralih ke perangkat seluler, animasi beralih ke CSS untuk sintaksis deklaratif dan browser pengoptimalan dapat menggunakannya. Karena 60 fps di perangkat seluler selalu menjadi sasaran Anda, jadi masuk akal untuk tidak pernah melampaui browser apa yang tahu cara menampilkannya secara efisien.

Kini muncul semakin banyak alat untuk membuat animasi berbasis JavaScript lebih efisien, tetapi masalahnya adalah perpaduan dari animasi deklaratif dan imperatif , dengan keputusan cara menulis animasi Anda didasarkan pada kode yang paling jelas, bukan apa yang mungkin dalam satu bentuk dan bukan dalam bentuk yang lain.

Animasi Web akan menjawab panggilan tersebut, dan bagian pertamanya ada di Chrome 36 dalam bentuk element.animate(). Fungsi baru ini memungkinkan Anda membuat animasi hanya dalam JavaScript dan menjalankannya seefisien Animasi atau Transisi CSS mana pun (pada kenyataannya, mulai Chrome 34, mesin Animasi Web yang sama persis menjalankan semua metode ini).

Sintaksisnya sederhana, dan bagian-bagiannya seharusnya tidak asing bagi Anda jika Anda pernah menulis Transisi atau Animasi CSS:

element.animate([
    {cssProperty: value0},
    {cssProperty: value1},
    {cssProperty: value2},
    //...
], {
    duration: timeInMs,
    iterations: iterationCount,
    delay: delayValue
});

Keuntungan terbesar dari fungsi baru ini adalah menghilangkan banyak lingkaran canggung yang sebelumnya harus kita lewati untuk mendapatkan animasi yang mulus dan bebas jank.

Misalnya, untuk Pelacak Sinterklas tahun lalu, kami ingin salju terus turun, dan kami memutuskan untuk menganimasikannya melalui CSS agar dapat dilakukan dengan sangat efisien.

Namun, kita ingin memilih posisi horizontal salju secara dinamis berdasarkan layar dan peristiwa yang terjadi dalam adegan itu sendiri, dan tentu saja ketinggian salju yang turun (tinggi jendela browser pengguna) tidak akan diketahui sampai kita benar-benar berjalan. Artinya, kami benar-benar harus menggunakan Transisi CSS, karena pembuatan Animasi CSS saat runtime menjadi kompleks dengan cepat (dan ratusan serpihan salju berarti ratusan aturan gaya baru).

Jadi, kami mengambil pendekatan berikut, yang seharusnya familier:

snowFlake.style.transform = 'translate(' + snowLeft + 'px, -100%)';
// wait a frame
snowFlake.offsetWidth;
snowFlake.style.transitionProperty = 'transform';
snowFlake.style.transitionDuration = '1500ms';
snowFlake.style.transform = 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)';

Kuncinya ada dalam komentar 'tunggu frame' itu. Agar berhasil memulai transisi, browser harus mengakui bahwa elemen berada di posisi awal. Ada beberapa cara untuk melakukannya. Salah satu cara yang paling umum adalah membaca dari salah satu properti elemen yang memaksa browser untuk menghitung tata letak, sehingga memastikan browser mengetahui bahwa elemen memiliki posisi awal sebelum bertransisi ke posisi akhir. Dengan menggunakan metode ini, Anda dapat memberi selamat kepada diri sendiri atas pengetahuan Anda yang luar biasa tentang internal browser sambil tetap merasa kotor dengan setiap penekanan tombol.

Sebaliknya, panggilan element.animate() yang setara tidak dapat lebih jelas, yang menyatakan secara persis apa yang dimaksudkan:

snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);

Ada banyak opsi lainnya. Sama seperti animasi pada umumnya, Animasi Web dapat ditunda dan diiterasi:

snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], {
    duration: 1500,
    iterations: 10,
    delay: 300
});

AnimationPlayer

element.animate() benar-benar menampilkan objek AnimationPlayer, yang akan menjadi semakin penting seiring semakin banyak spesifikasi Web Animations yang diluncurkan. Baik animasi buatan JavaScript maupun CSS akan memiliki AnimationPlayers terkait, yang memungkinkannya untuk dikombinasikan secara mulus dengan cara yang berguna dan menarik.

Untuk saat ini, AnimationPlayer hanya memiliki dua fungsi, keduanya sangat berguna. Anda dapat membatalkan animasi kapan saja menggunakan AnimationPlayer.cancel():

var player = snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);
// less than 1500ms later...changed my mind
player.cancel();

Dan, untuk melegakan semua orang yang pernah mencoba membangun sistem animasi seputar Animasi atau Transisi CSS di masa lalu, Animasi Web selalu mengaktifkan peristiwa setelah selesai:

var player = snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);
player.onfinish = function(e) {
    console.log('per aspera ad terra!');
}

Cobalah

Semua ini dikirim untuk Chrome 36, beralih ke beta sekarang. Jika Anda ingin mencobanya, coba gunakan implementasi native di Chrome 36. Namun, ada polyfill Web Animations yang secara signifikan menghadirkan bagian yang jauh lebih besar dari spesifikasi Animasi Web lengkap ke browser modern mana pun yang evergreen.

Demo efek salju tersedia bagi Anda untuk mencoba menggunakan versi native dari element.animate() dan polyfill.

Beri tahu kami pendapat Anda

Sebenarnya, ini adalah pratinjau dari apa yang akan datang, dan akan dirilis khusus untuk segera mendapatkan masukan dari developer. Kami belum yakin apakah kami sudah mencapai setiap kasus penggunaan, atau mengampelas setiap tepian kasar API saat ini untuk animasi. Satu-satunya cara bagi kami untuk mengetahui dan benar-benar melakukannya adalah dengan mencobanya dan memberi tahu kami pendapat mereka.

Komentar pada postingan ini tentu saja bermanfaat, dan komentar pada standar itu sendiri dapat dialamatkan ke CSS dan SVG Working Group melalui milis public-fx.

Pembaruan, Oktober 2014: Chrome 39 menambahkan dukungan untuk beberapa metode tambahan yang terkait dengan mengontrol pemutaran, seperti play(), pause(), dan reverse(). Fitur ini juga mendukung lompat ke titik tertentu dalam linimasa animasi melalui properti currentTime. Anda dapat melihat cara kerja fungsi ini di demo baru ini.

Terima kasih kepada Addy Osmani dan Max Heinritz atas bantuan mereka terkait postingan ini.