Jika telah menggunakan requestAnimationFrame
, Anda akan senang melihat cat Anda disinkronkan dengan kecepatan refresh layar, sehingga menghasilkan animasi dengan fidelitas setinggi mungkin. Selain itu, Anda menghemat suara kipas CPU dan daya baterai pengguna saat mereka beralih ke tab lain.
Namun, akan ada perubahan pada bagian API. Stempel waktu yang diteruskan ke fungsi callback Anda berubah dari stempel waktu seperti Date.now()
standar menjadi pengukuran milidetik floating point beresolusi tinggi sejak halaman dibuka. Jika menggunakan nilai ini, Anda harus mengupdate kode, berdasarkan penjelasan di bawah.
Agar tidak ada kesalahpahaman, berikut yang saya maksud:
// assuming requestAnimationFrame method has been normalized for all vendor prefixes..
requestAnimationFrame(function(timestamp){
// the value of timestamp is changing
});
Jika menggunakan shim requestAnimFrame
umum yang disediakan di sini, Anda tidak menggunakan nilai stempel waktu. Anda bebas dari masalah. :)
Mengapa
Mengapa? rAF membantu Anda mendapatkan 60 fps terbaik yang ideal, dan 60 fps berarti 16,7 md per frame. Namun, pengukuran dengan milidetik bilangan bulat berarti kita memiliki presisi 1/16 untuk semua hal yang ingin diamati dan ditargetkan.

Seperti yang dapat Anda lihat di atas, batang biru menunjukkan jumlah waktu maksimum yang Anda miliki untuk melakukan semua pekerjaan sebelum Anda menggambar frame baru (pada 60 fps). Anda mungkin melakukan lebih dari 16 hal, tetapi dengan milidetik bilangan bulat, Anda hanya dapat menjadwalkan dan mengukur dalam penambahan yang sangat besar. Itu tidak cukup baik.
Timer Resolusi Tinggi mengatasi hal ini dengan memberikan angka yang jauh lebih akurat:
Date.now() // 1337376068250
performance.now() // 20303.427000007
Timer resolusi tinggi saat ini tersedia di Chrome sebagai window.performance.webkitNow()
, dan nilai ini umumnya sama dengan nilai argumen baru yang diteruskan ke callback rAF. Setelah spesifikasi berkembang lebih lanjut melalui standar, metode akan menghapus awalan dan tersedia melalui performance.now()
.
Anda juga akan melihat bahwa kedua nilai di atas memiliki perbedaan yang sangat besar. performance.now()
adalah pengukuran milidetik floating point sejak halaman tertentu mulai dimuat (performance.navigationStart
secara spesifik).
Sedang digunakan
Masalah utama yang muncul adalah library animasi yang menggunakan pola desain ini:
function MyAnimation(duration) {
this.startTime = Date.now();
this.duration = duration;
requestAnimFrame(this.tick.bind(this));
}
MyAnimation.prototype.tick = function(time) {
var now = Date.now();
if (time > now) {
this.dispatchEvent("ended");
return;
}
...
requestAnimFrame(this.tick.bind(this));
}
Pengeditan untuk memperbaikinya cukup mudah... tambahkan startTime
dan now
untuk menggunakan window.performance.now()
.
this.startTime = window.performance.now ?
(performance.now() + performance.timing.navigationStart) :
Date.now();
Ini adalah implementasi yang cukup naif, tidak menggunakan metode now()
dengan awalan dan juga mengasumsikan dukungan Date.now()
, yang tidak ada di IE8.
Deteksi fitur
Jika tidak menggunakan pola di atas dan hanya ingin mengidentifikasi jenis nilai callback yang Anda dapatkan, Anda dapat menggunakan teknik ini:
requestAnimationFrame(function(timestamp){
if (timestamp < 1e12){
// .. high resolution timer
} else {
// integer milliseconds since unix epoch
}
// ...
Memeriksa if (timestamp < 1e12)
adalah pengujian cepat untuk melihat seberapa besar angka yang kita hadapi. Secara teknis, hal ini dapat menjadi positif palsu, tetapi hanya jika halaman web terbuka terus-menerus selama 30 tahun. Namun, kita tidak dapat menguji apakah nilai tersebut merupakan bilangan floating point (bukan bilangan bulat). Minta timer resolusi tinggi yang cukup dan Anda pasti akan mendapatkan nilai bilangan bulat pada suatu saat.
Kami berencana menerapkan perubahan ini di Chrome 21, jadi jika Anda sudah memanfaatkan parameter callback ini, pastikan untuk memperbarui kode Anda.