requestAnimationFrame
sürümünü kullanıyorsanız boyalarınızın ekranın yenileme hızıyla senkronize edilmesini ve bunun sonucunda mümkün olan en yüksek kaliteli animasyonlara sahip olmayı sevmişsinizdir. Ayrıca, kullanıcılarınız başka bir sekmeye geçtiğinde CPU fan gürültüsünü ve pil gücünü de tasarruf etmiş olursunuz.
Ancak API'nin bir kısmında değişiklik yapılacaktır. Geri çağırma işlevinize iletilen Zaman Damgası, Date.now()
benzeri tipik bir zaman damgasından, sayfanın açılmasından bu yana geçen milisaniye cinsinden yüksek çözünürlüklü bir ölçüme dönüşüyor. Bu değeri kullanıyorsanız aşağıdaki açıklamaya göre kodunuzu güncellemeniz gerekir.
Konuyu netleştirmek için şunu belirtmek isterim:
// assuming requestAnimationFrame method has been normalized for all vendor prefixes..
requestAnimationFrame(function(timestamp){
// the value of timestamp is changing
});
Burada sağlanan yaygın requestAnimFrame
shim'i kullanıyorsanız zaman damgası değerini kullanmıyorsunuz demektir. Yayından ayrıldınız. :)
Neden?
Neden? rAF, ideal olan 60 fps'yi elde etmenize yardımcı olur. 60 fps, kare başına 16,7 ms'ye karşılık gelir. Ancak tam milisaniyelerle ölçüm yapmak, gözlemlemek ve hedeflemek istediğimiz her şey için 1/16 hassasiyete sahip olduğumuz anlamına gelir.
Yukarıda görebileceğiniz gibi mavi çubuk, yeni bir kare çizmeden önce tüm çalışmanızı tamamlamanız için gereken maksimum süreyi (60 fps'de) gösterir. Muhtemelen 16'dan fazla şey yapıyorsunuzdur ancak tam milisaniyeler kullanırken yalnızca bu çok büyük artışlarla planlama ve ölçüm yapabilirsiniz. Bu yeterli değil.
Yüksek Çözünürlüklü Zamanlayıcı, çok daha hassas bir değer sunarak bu sorunu çözer:
Date.now() // 1337376068250
performance.now() // 20303.427000007
Yüksek çözünürlüklü zamanlayıcı şu anda Chrome'da window.performance.webkitNow()
olarak kullanılabilir ve bu değer genellikle rAF geri çağırma işlevine iletilen yeni bağımsız değişken değerine eşittir. Spesifikasyon standartlar açısından daha da ilerlediğinde yöntem, öneki kaldıracak ve performance.now()
üzerinden kullanılabilir olacaktır.
Ayrıca, yukarıdaki iki değerin birçok farklı büyüklük sıralaması olduğunu göreceksiniz. performance.now()
, söz konusu sayfanın yüklenmeye başlamasından itibaren geçen milisaniyelerin kayan noktalı ölçümüdür (daha açık belirtmek gerekirse performance.navigationStart
).
Kullanımda
Kırpılan temel sorun, şu tasarım kalıbını kullanan animasyon kitaplıklarıdır:
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));
}
Bu sorunu düzeltmek için yapmanız gereken düzenleme oldukça kolaydır. startTime
ve now
öğelerini window.performance.now()
öğesini kullanacak şekilde değiştirin.
this.startTime = window.performance.now ?
(performance.now() + performance.timing.navigationStart) :
Date.now();
Bu oldukça saf bir uygulamadır. Ön ek içeren bir now()
yöntemi kullanmaz ve IE8'de bulunmayan Date.now()
desteğini varsaymaz.
Özellik algılama
Yukarıdaki kalıbı kullanmıyorsanız ve yalnızca hangi tür geri çağırma değerini aldığınızı belirlemek istiyorsanız aşağıdaki tekniği kullanabilirsiniz:
requestAnimationFrame(function(timestamp){
if (timestamp < 1e12){
// .. high resolution timer
} else {
// integer milliseconds since unix epoch
}
// ...
if (timestamp < 1e12)
sayısını kontrol etmek, ne kadar büyük bir sayıyla uğraştığımızı anlamanızı sağlayacak hızlı bir ördek testidir. Teknik olarak yanlış pozitif olabilir ancak yalnızca bir web sayfası 30 yıl boyunca sürekli açıksa. Ancak bunun bir kayan nokta olup olmadığını (bir tamsayıya yuvarlanmak yerine) test edemeyiz. Yeterince yüksek çözünürlüklü zamanlayıcı isteğinde bulunursanız bir noktada tam sayı değerleri alırsınız.
Bu değişikliği Chrome 21'de kullanıma sunmayı planlıyoruz. Bu geri çağırma parametresinden zaten yararlanıyorsanız kodunuzu güncellemeyi unutmayın.