Holodepth • ByteOmi Köprü • Zamanlama
requestAnimationFrame
Ekran ritmini mi takip ediyorsun, yoksa kendi ritmini mi dayatıyorsun? rAF, “ekran hazır olduğunda çağır” der; setInterval ise sabit bir zamanlayıcı ritmine bağlanır — bu da animasyonlarda drift/jitter üretir.
Bu köprü sayfası render loop’un anatomisini sıfırdan anlatmak için değil; “neden rAF kullanılır?” hissini kurmak için durur: recursive kullanım modeli, high‑res timestamp ile \(\Delta t\) ve main-thread üzerindeki iş yükünün etkisi.
Kaynak metin: byteomi.com • Önceki köprü: Render Loop • Loop’un “kalp atışı” ile birlikte düşün.
Neden setInterval animasyonları bozar? — “Browser Pulse Monitor”
Soruyu şöyle kur: ekranın ritmini mi takip ediyorsun, yoksa kendi ritmini mi dayatıyorsun? Radar çizgisi her tick’te ilerler; stamp’ler (iz noktaları) “tick düzeni”ni görünür kılar. rAF modunda düzen stabil kalır; setInterval modunda ise zamanlayıcı ile gerçek dünya zamanı uyumsuzlaşır ve jitter/drift büyür. Jammer’ı açarak main thread’i şişir ve ritmin nasıl kekeleyeceğini izle.
Hero demo
Bu demo render loop’un anatomisini değil; neden rAF kullanılır hissini verir: ekranla senkron ritim vs zamanlayıcı drift/jitter • recursive start/stop • timestamp → Δt • main-thread jammer.
İpucu: Jammer açıkken rAF de gecikir; “doğru seçim” kadar tick içini hafif tutmak da önemlidir.
Neden rAF?
setInterval/setTimeout monitörün o an ne yaptığını bilmez. Ekran 60Hz tazeliyorsa zamanlayıcı 61. kez çizim denemesi yapabilir; bu da VSync uyumsuzluğu ve tearing riskini artırır. rAF ise “ekran hazır olduğunda çağır” diyerek ritmi ekrana bağlar.
rAF mucize değildir: callback hâlâ main thread üstünde çalışır. Tick içinde ağır işler yaparsan rAF de gecikir ve stutter üretir.
Recursive (özyinelemeli) yapı
rAF kendiliğinden devam etmez: her tick’te bir sonraki kareyi tekrar istersin. Bu küçük fark kontrolü büyütür: pause/resume, modal açılınca render’ı durdurma, yanlışlıkla iki loop’u aynı anda çalıştırmama gibi.
rAF bir “id” döndürür. Bu id’yi saklayıp cancelAnimationFrame ile iptal edebilmek, çift render / çift update gibi
maliyetli hataları engeller.
Zaman damgası: High‑res timestamp
rAF callback’i bir timestamp verir. İki kare arasındaki farkı alarak \(\\Delta t\\) hesaplar ve hareketi “frame sayısına” değil “gerçek zamana” bağlarsın. Yaygın hata: timestamp’i saniye sanmak — çoğu ortamda milisaniyedir; hızın birim/saniye ise \(\\Delta t\\)’yi saniyeye çevirmelisin.
Sekmeye gidip geri geldiğinde \(\\Delta t\\) büyüyebilir. Bu yüzden clamp veya fixed‑step gibi disiplinler devreye girer.
CPU–GPU senkronizasyonu: Frame bundle
rAF, DOM/CSS güncellemeleri ile WebGL çizim komutlarını aynı “kare paketi” içinde toplamaya çalışır. Bu sayede update→render ritmi tarayıcının çizim zamanı ile daha öngörülebilir şekilde hizalanır.
Akıcılık bozulduğunda çoğu zaman sorun rAF’in kendisi değil; tick içinde biriken iş yüküdür. Hedef, frame bütçesini yönetmektir.