Animasi di web pernah menjadi wilayah JavaScript, tetapi seiring dunia beralih ke perangkat seluler, animasi beralih ke CSS untuk sintaksis deklaratif dan pengoptimalan yang dapat dilakukan browser dengannya. Dengan 60 fps di perangkat seluler yang selalu menjadi sasaran Anda, sebaiknya jangan pernah melampaui kemampuan browser untuk menampilkan secara efisien.
Semakin banyak alat yang muncul untuk membuat animasi yang didorong JavaScript menjadi lebih efisien, tetapi yang paling penting adalah penyatuan animasi deklaratif dan imperatif , dengan keputusan tentang cara menulis animasi didasarkan pada kode yang paling jelas, bukan yang mungkin dalam satu bentuk dan tidak dalam bentuk lainnya.
Animasi Web siap menjawab panggilan tersebut, dan bagian pertamanya telah hadir di Chrome 36 dalam bentuk element.animate()
. Fungsi baru ini memungkinkan Anda membuat animasi sepenuhnya di JavaScript dan menjalankannya seefisien Animasi atau Transisi CSS (bahkan, mulai Chrome 34, mesin Web Animation yang sama persis mendorong semua metode ini).
Sintaksisnya sederhana, dan bagian-bagiannya akan Anda kenal jika 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 penghapusan banyak rintangan canggung yang sebelumnya harus kita lalui untuk mendapatkan animasi yang lancar dan bebas jank.
Misalnya, untuk Santa Tracker tahun lalu, kami ingin salju turun terus-menerus, 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 di tampilan itu sendiri, dan tentu saja tinggi salju yang turun (tinggi jendela browser pengguna) tidak akan diketahui hingga kita benar-benar berjalan. Artinya, kita benar-benar harus menggunakan Transisi CSS, karena penulisan Animasi CSS saat runtime menjadi sangat kompleks dengan cepat (dan ratusan kepingan salju berarti ratusan aturan gaya visual baru).
Jadi, kami menggunakan pendekatan berikut, yang seharusnya sudah Anda pahami:
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'. Agar berhasil memulai transisi, browser harus mengonfirmasi 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 menghitung tata letak, sehingga memastikan browser mengetahui bahwa elemen memiliki posisi awal sebelum bertransisi ke posisi akhir. Dengan menggunakan metode ini, Anda dapat memuji diri sendiri atas pengetahuan yang unggul tentang internal browser sambil tetap merasa kotor dengan setiap penekanan tombol.
Sebaliknya, panggilan element.animate()
yang setara tidak bisa lebih jelas, yang menyatakan dengan tepat apa yang dimaksud:
snowFlake.animate([
{transform: 'translate(' + snowLeft + 'px, -100%)'},
{transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);
Ada banyak opsi lainnya. Sama seperti CSS, Web Animations dapat ditunda dan di-iterasi:
snowFlake.animate([
{transform: 'translate(' + snowLeft + 'px, -100%)'},
{transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], {
duration: 1500,
iterations: 10,
delay: 300
});
AnimationPlayer
element.animate()
sebenarnya menampilkan objek AnimationPlayer, yang akan semakin penting seiring semakin banyak spesifikasi Animasi Web yang diluncurkan. Animasi yang dibuat dengan JavaScript dan CSS akan memiliki AnimationPlayers terkait, sehingga animasi tersebut dapat digabungkan dengan lancar dengan cara yang berguna dan menarik.
Namun, untuk saat ini, AnimationPlayer hanya memiliki dua bagian 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 meringankan beban semua orang yang telah mencoba membuat sistem animasi di sekitar Animasi atau Transisi CSS sebelumnya, Animasi Web selalu memicu peristiwa saat 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
Semuanya akan dikirimkan di Chrome 36, yang akan beralih ke versi beta hari ini. Jika Anda ingin mencobanya, coba gunakan penerapan native di Chrome 36. Namun, ada polyfill Animasi Web, yang menghadirkan sebagian besar spesifikasi Animasi Web lengkap ke browser modern yang selalu aktif.
Demo efek salju tersedia untuk Anda coba menggunakan element.animate()
versi native dan polyfill.
Beri tahu kami pendapat Anda
Namun, ini adalah pratinjau dari hal yang akan datang, dan dirilis secara khusus untuk segera mendapatkan masukan developer. Kami belum yakin apakah kami telah memenuhi setiap kasus penggunaan, atau telah menyelesaikan setiap kekurangan API saat ini untuk animasi. Satu-satunya cara bagi kami untuk mengetahui dan benar-benar melakukannya dengan benar adalah dengan meminta developer untuk mencobanya dan memberi tahu kami pendapat mereka.
Komentar pada postingan ini tentu saja berharga, dan komentar tentang standar itu sendiri dapat ditujukan kepada CSS dan SVG Working Group melalui daftar рассылки public-fx.
Pembaruan, Oktober 2014: Chrome 39 menambahkan dukungan untuk beberapa metode tambahan yang terkait dengan kontrol pemutaran, seperti play()
, pause()
, dan reverse()
. Fungsi ini juga mendukung lompatan ke titik tertentu dalam linimasa animasi melalui properti currentTime
. Anda dapat melihat fungsi ini beraksi di demo baru ini.
Terima kasih kepada Addy Osmani dan Max Heinritz atas bantuannya dalam membuat postingan ini.