holodepth

HTML5 Canvas · Render döngüsü

requestAnimationFrame ile kare planlama

RequestAnimationFrame, tarayıcıya «bir sonraki boyama ile hizalı bir an çalış» dersiniz — özellikle Canvas 2D gibi raster yollarında her karede clearRect + geometri + stil ile yüzeyi yeniden kuruyorsanız fiilen üretim tetikleyiciniz budur. Bu sayfa, zaman damgasını nasıl okuyacağınızı, döngüyü nasıl güvenle açıp kapatacağınızı ve görünürlük / yenileme hızı yüzünden beklenen kare sıklığını nasıl modellediğinizi canvas üreticisi gözünden sabitler; genel game loop mimarisinin tamamı burada anlatılmaz.

Piksel düzenini sıfırlama ve katman sırası Clear & redraw konusunda; bağlam stili ve kırpma State sistemi ile yönetilir — burada yalnızca ne zaman çizim fonksiyonunuzun çağrılacağı ve o çağrıya hangi zaman verisinin eşlik edeceği ön plandadır.

Özet: rAF ve yakın alternatifler

Yol Canvas ile ilişki Dikkat
requestAnimationFrame Ekran yenilemesiyle uyumlu kare; çoğu animasyonlu canvas için varsayılan Sekme gizliyken sıklık düşer veya durur; tek başına iş garantisi vermez
setInterval / setTimeout Sabit ms ile mantık güncellemesi; çizim hâlâ rAF ile senkronlamak iyidir Görünür olmayan sekmede bile çalışabilir; pil ve CPU israfı
Tek seferlik çizim (olay tetikli) Statik grafik veya kullanıcı etkileşimi sonrası tek draw Sürekli hareket için rAF veya benzeri zamanlama gerekir

Tarayıcı zamanlayıcısı ve piksel tazeliği

Canvas hedefiniz ekranda olduğu sürece, kullanıcı hareketli bir gözlenti bekler — yeni kare üretmeden önceki pikseller ekranda kalır. rAF, bu «tazelik» talebini tarayıcının ana döngüsüne bağlar: geri çağrınız genelde düzenleme ve boyama aşamalarına yakın çalışır, böylece drawImage, yol doldurma ve stil güncellemeleri tek bir görsel atımında toplanır.

Bu, ekran kartını sürekli kullanmama sözü değildir; yoğun çizim hâlâ GPU / kompozitör maliyetini taşır. rAF’ın vaadi karelerin görüntüleme ritmiyle çarpışmama ve gereksiz boş döngüleri azaltma eğilimidir — özellikle setInterval(16) ile iki kez örnekleyip yarım kare gecikmesi yaratmaktan daha öngörülebilir bir tablo sunar.

Offscreen canvas veya transferControlToOffscreen senaryolarında ana ileti dizisi hâlâ görünür yüzeyi sunar; worker tarafı ayrı planlanır — bu sayfada odak, ana belgede çalışan klasik 2D bağlamındaki rAF kullanımıdır.

Callback, zaman damgası ve cancelAnimationFrame

requestAnimationFrame(callback) size bir kimlik döner; aynı geri çağrı içinde veya durdurmak istediğiniz anda cancelAnimationFrame(id) ile plan iptal edilir. Kimliği kaybetmek, uygulama yaşam döngüsünde (ör. rota değişimi, bileşen unmount) «hayalet kare» bırakmanın yaygın nedenidir.

Tarayıcı, geri çağrınıza genelde DOM yüksek çözünürlüklü zaman damgası (DOMHighResTimeStamp) iletir; bu değer milisaniye cinsinden monotonik bir süredir ve kareler arası farkı alarak delta üretmek için uygundur. Tarih nesnesi (Date.now) ile karıştırmayın — görsel simülasyon için monotonik süre daha güvenilirdir.

Tek bir dizi içinde birden fazla kez rAF planlamak mümkündür fakat çoğu canvas uygulaması tek aktif planlayıcı desenini seçer: dış döngü fonksiyonu sonunda yalnızca bir requestAnimationFrame(loop) çağrısı; içeride o kareye özel çizim ve mantık. Böylece eşzamanlı iki planlı döngü yarışı önlenir.

function startCanvasLoop(ctx, step) {
  let rafId = 0;
  let prev = 0;

  const loop = (now) => {
    const dt = prev ? (now - prev) / 1000 : 0;
    prev = now;
    step(ctx, dt, now);
    rafId = requestAnimationFrame(loop);
  };

  return {
    start() {
      cancelAnimationFrame(rafId);
      prev = 0;
      rafId = requestAnimationFrame(loop);
    },
    stop() {
      cancelAnimationFrame(rafId);
      rafId = 0;
      prev = 0;
    },
  };
}

Görünürlük ile kare sıklığı

Sekme arka planda veya pencere minimize olduğunda tarayıcı geri çağrınızı seyreltir veya durdurabilir; bu, canvas tabanlı oyun veya veri grafiği için pil dostu davranıştır; fakat simülasyonun «gerçek zamanlı» ilerlemesi gerekiyorsa mantıksal saati rAF dışında da ilerletmek (ör. ağ veya fizik düğümü) ayrı bir mimari karar olur — burada yalnızca çizimin sekme durumuna bağlı yavaşladığını hatırlatırız.

document.visibilityState ve visibilitychange olayı ile kullanıcı arayüzünüzü dondurabilir, kare sayacını sıfırlayabilir veya ilk görünür olduğunuz karede tek seferlik tam yeniden çizim planlayabilirsiniz. İlk karede ani sıçrama yaşamamak için prev zaman damgasını sıfırlamak sık kullanılır.

Variable refresh rate (VRR) ve display özellikleri cihaza göre değişir; 60 fps varsayımı artık evrensel değildir — delta tabanlı hareket kodu, sabit 1/60 çarpanına göre daha az titreşim üretir.

Delta süre ve animasyon adımı

İlk geri çağrıda delta sıfır veya tanımsız kabul edilir; ikinci kareden itibaren now - prev farkı ölçeklenerek saniye cinsinden adım süresi elde edilir. Canvas üzerinde yörünge, yayılma veya parçacık konumunu her karede += hız * dt biçiminde güncellemek, kare hızı 30 ile 120 arasında salındığında bile yaklaşık aynı fiziksel hızı korur.

Uzun bir sekme donmasından sonra delta büyük gelebilir; simülasyonu patlatmamak için üst sınır ( clamp) uygulamak interaktif canvaslarda yerleşik bir uygulamadır — değer seçimi oyun hissi ile ölçülür, API tarafında zorunlu kural yoktur.

rAF geri çağrısı içinde ağır senkron iş yükü (büyük JSON ayrıştırma, bloklayıcı döngü) ana iş parçacığını kilitleyip hem çizimi hem giriş olaylarını geciktirdiğinden, veri hazırlığını mümkün olduğunca kareden önce veya asenkron kanallara itmek canvas akıcılığı için aynı önemdedir; konu worker / mesajlaşma ayrıntısı bu sayfanın sınırı dışındadır.

Başlatma, durdurma ve tek planlayıcı kimliği

Aynı canvas’ı birden fazla modül «sahipleniyorsa» çift rAF zinciri oluşur; bu, aynı piksel yığınının iki kez temizlenmesi veya stil sızdırması gibi hatalara yol açar. Çözüm: tek bir orkestrasyon katmanında kare planlayın, alt sistemler yalnızca kare başına bir kez çağrılan arayüz fonksiyonları sunsun.

start çağrısından önce varsa eski kimliği iptal etmek, React / Vue gibi çerçevelerde bileşen yeniden bağlandığında üst üste binen döngüleri engeller. Kütüphane yazıyorsanız «açık döngü bırakmama» sözleşmesini belgeleyin.

Olay dinleyicisi içinde (ör. fare ile sürükleme) her hareket anında tam sahne çizmek yerine bazen yalnızca bir «kirli bayrağı» kaldırıp rAF içinde tekilleştirilmiş çizim yapmak, aynı karede onlarca çağrıyı tek composite yoluna indirger — bu desen hem girdi gecikmesini hem de işlemcinin gereksiz tekrarını azaltır.

Temizleme ve yeniden çizim sırası

Tipik animasyon karesi: arka planı temizle veya opak zemin çiz → dünya geometrisini çiz → HUD / ölçüm katmanını çiz. rAF geri çağrınız, bu sırayı tek bir atomik «görünür kare» halinde tamamlamalıdır; yarım bırakılmış ara durumları kullanıcı görmemelidir.

Boyut değişimi (geri çağrı dışında) piksel ölçeğini etkiler — resize sonrası ilk rAF çağrısında tam yeniden kurulum sık pattern’dir ( Resize mantığı ). Temizlik stratejisi (clearRect mi, tuvale dolgu mu) ayrıntısı Clear & redraw sayfasında tutulur; burada yalnızca «rAF içinde tek geçişte bitirin» kuralı özetlenir.

Çift tampon veya offscreen birleşimi kullanıyorsanız, ana yüzeye yapıştırma çağrısı da aynı karede tamamlanmalıdır; aksi halde ara karede eski ve yeni bitmap karışımı bir anlık görünür.

Anti-kalıplar: döngü ve zamanlama

rAF + setInterval çift motor: İki kaynak zamanı birleştirmeden aynı canvas’a yazmak yarış durumu üretir — ya tek motor seçin ya da biri yalnızca mantık, diğeri yalnızca çizim olsun ve sözleşmeyi yazın.

İptal atlamak: Bileşen yok olduğunda planlı geri çağrı devam ederse bellek ve hata konsolu «ghost» üretir; kimliği her zaman saklayın.

Sabit fps varsayımı: Kodda 1/60 sakızlamak, yüksek yenilemeli ekranda yavaşlama, düşük yenilemede ise adım atlama hissi verir — tercihen ölçülen delta.

Aynı karede onlarca çizim: Olay fırtınası sırasında doğrudan draw çağırmak yerine kare içinde birleştirme ( §5 ) düşük gecikmeli his verir.

Bu sayfanın sınırı

WebGL veya WebGPU komut kuyruğu, tarayıcının kendi kare zamanlamasından farklı katmanlarda çalışabilir; burada anlatılan sözleşme özellikle CanvasRenderingContext2D ve ana iş parçacığında çalışan görsel güncelleme için yazılmıştır.

Ses zamanlaması (Web Audio), ağ gecikmesi ve sunucu otoritesi gibi konular sahne saati ile çakışabilir; tek bir rAF geri çağrısı tüm sistemin hakemliği değildir — yalnızca görüntü üretim zamanı için güçlü bir kancadır.

  • Kare planlayıcı kimliği saklanıyor ve durumda iptal ediliyor mu?
  • delta ilk kare ve uzun duraklamadan sonra sınırlanıyor mu?
  • Sekme gizliyken mantık ile çizim aynı varsayımla mı ilerliyor?
  • Aynı yüzeye birden fazla bağımsız rAF zinciri var mı?
  • Tek karede çizim atomik tamamlanıyor mu (yarım ara durum yok)?