holodepth

HTML5 Canvas · Render döngüsü

Clear & redraw: piksel buffer’ını yenilemek

Canvas 2D yüzeyi, bellekte sabit boyutlu bir piksel ızgarasıdır — yeni bir karede eski çizimleri «üstüne boyamadan» önce hangi bölgeleri sileceğinize veya hangi arka planı kuracağınıza karar verirsiniz. clearRect belirtilen dikdörtgende pikselleri tam şeffaflığa döndürür; bu, sayfadaki düz renk CSS arka planının görünmesine veya alt katman DOM öğelerinin etkisine yol açabilir. Bu sayfa, temizlemenin ne işe yaradığını, tam yüzey ile kısmi temizlik ayrımını, opak zemin tercihini ve animasyon karesi içindeki sırayı canvas üreticisi gözüyle sabitler.

Kare zamanlaması requestAnimationFrame ve Delta time konularında; bağlam dönüşümü ve kırpma State sistemi ile yönetilir — burada yalnızca piksel öncesi alanın nasıl sıfırlanacağı ön plandadır.

Özet: temizleme yolları

Yöntem Sonuç Canvas’ta tipik kullanım
clearRect Alan şeffaf olur (alfa 0) Her kare tam sahne; parallax için transparan gökyüzü katmanı
fillRect (tüm yüzey) Opak veya yarı saydam boya Düz renk oyun zeminı; CSS arkası görünmez
Kısmi clearRect Yalnız seçilen hücre temizlenir Düşük maliyetli grafik güncellemesi, debug ızgarası
Boşluk: temizleme yok Önceki kare pikselleri kalır İz bırakan çizim, motion blur benzeri deney (bilinçli)

Tam yüzey ve kısmi temizlik: ne siler, ne korunur

Temizlik komutu yalnızca hedeflediğiniz piksel alt örneklemini etkiler — yol nesnesi, bağlam stili veya dönüşüm matrisi silinmez; bunlar beginPath, save/restore veya açık özellik atamalarıyla ayrı yönetilir. Bu yüzden «sahneyi temizledim» dediğinizde kastınız çoğunlukla bitmap’i sıfırlamaktır: geometri komutlarını tekrar vermek yine sizin görevinizdir.

Kısmi temizlik, büyük statik arka planı her karede yeniden çizmekten kaçınmak için kullanılır; fakat hareketli öğe eski piksel konumunu da terk ediyorsa, ya hareket alanını geniş bir dikdörtgende temizlersiniz ya da tam kare yenilersiniz — aksi halde eski çizimden piksel artığı («hayalet görüntü») kalır.

Global globalCompositeOperation ve globalAlpha aktifken clearRect hâlâ hedef pikselleri şeffaflaştırır; yine de karışıklığı azaltmak için tam yüzey temizliğini çoğu projede nötr modda yapmak, hata ayıklamayı ve bir sonraki çizim turunu öngörmeyi kolaylaştırır ( Composite · source-over kısa köprü).

clearRect sözleşmesi ve dönüşüm uzayı

clearRect(x, y, w, h) çağrısı geçerli dönüşüm matrisi altında çalışır — önce translate/rotate/scale uyguladıysanız temizlenen dikdörtgen ekranda dönmüş veya kaymış görünür. Tam yüzeyi ekran eksenine hizalı silmek için temizlikten önce matrisi kimliğe çekmek veya ayrı bir save dalında setTransform(1,0,0,1,0,0) kullanmak standart güvenli kalıptır.

Genişlik veya yükseklik negatifse dikdörtgen ters yönde büyür; bu, düzen hesaplarında yararlı olabilir fakat tam yüzey temizliğinde genelde pozitif width = canvas.width, height = canvas.height ile çağrılır — boyutlar, CSS ile ölçeklenmiş görünse bile bağlamın dahili piksel boyutlarıdır ( Resize mantığı ).

clearRect yolu açmaz; dolayısıyla hemen ardından gelen stroke önceki path üzerinde beklenmedik segment üretmez — fakat path’i bilinçli sıfırlamıyorsanız farklı modüller arasında sızıntı yaşanır ( Path sistemi ).

/**
 * Bağlam ölçüsünde tüm yüzeyi şeffaflaştırır. Dönüşümden bağımsız çalışır.
 * canvas: HTMLCanvasElement, ctx: CanvasRenderingContext2D
 */
function clearFullSurface(ctx, canvas) {
  ctx.save();
  ctx.setTransform(1, 0, 0, 1, 0, 0);
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.restore();
}

Şeffaf temizlik ve opak zemin seçimi

Her karede sadece clearRect kullanırsanız çizilmeyen pikseller şeffaf kalır; tarayıcı tuvale, üstünde ve altında kalan katmanlarla birleştirir. Oyun dünyanız düz renkse, bazen CSS’te background-color yeterli görünür — fakat canvas içinde üst üste binmiş yarı saydam sprite’lar veya sonradan eklenen DOM overlay ile renk karışımı beklediğiniz gibi olmayabilir. Tam kontrol için çoğu ürün opak gövdeyi ilk iş olarak fillRect ile kendisi boyar.

Yarı saydam zemin (rgba(..., 0.07) gibi) bilinçli «iz bırakma» efekti üretir — bu, klasik temiz-redraw zincirinde sürpriz olabilir; ya tam şeffaf silip net yeniden çizin ya da iz efektini dokümante edin. İkisi birlikte yanlış sırada kullanılırsa arka planda eski kareler birikir.

globalAlpha düşükken tam yüzey fillRect ile boyamak hâlâ her piksele biraz renk döşer; performans ve görsel beklenti ayrı ölçülür — alpha ile oynamayı state dalına kısıtlamak sızıntıyı azaltır.

function paintOpaqueBackdrop(ctx, canvas, cssColor) {
  ctx.save();
  ctx.setTransform(1, 0, 0, 1, 0, 0);
  ctx.globalAlpha = 1;
  ctx.globalCompositeOperation = 'source-over';
  ctx.fillStyle = cssColor;
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  ctx.restore();
}

Kirli bölgeler ve kısmi yeniden çizim

Tüm sahneyi sürekli çizmek yerine yalnız değişen dikdörtgenleri yenilemek, eski arcade ve grafik editörü hissi veren klasik optimizasyondur. Şart: statik arka plan bir kez üretilebilir (arka tampon veya önbellekli bitmap) ve hareketli nesne dar bir kutuda kalır. Canvas’ta bu, clearRect + sınırlı bölge için çizim komutları anlamına gelir; dünya geneli karmaşıksa kirli kutu hesabı kod maliyeti tam boyama ile yarışabilir — ölçümle karar verilir.

Karmaşık senaryoda bir önceki sprite dikdörtgenini ve yenisini birleştirip tek geniş clearRect kullanmak, iki ayrı küçük temizlikten bazen daha verimli kompozit yoluna düşer. Parçacık sisleri gibi tüm yüzeyi bulanıklaştıran efektlerde bazı karelerde kısmi temizlik işe yaramaz; tam yenileme geri döner.

Kirli bölgeyi hesaplarken cihaz pikseli ve çizgi kalınlığını (stroke genişliği) unutmak, kenarlarda kirli piksel bırakır — minimum genişlik için tampon ( padding) eklemek yaygın düzeltmedir.

/**
 * world-space içinde kirli kutuyu temizleyip yeniden çizer (örn. sprite).
 * drawRegion: (ctx, rect) => void — çağıran sınırları bilir.
 */
function redrawRegion(ctx, rect, drawRegion) {
  const pad = 2;
  const x = Math.floor(rect.x - pad);
  const y = Math.floor(rect.y - pad);
  const w = Math.ceil(rect.w + pad * 2);
  const h = Math.ceil(rect.h + pad * 2);
  ctx.save();
  ctx.clearRect(x, y, w, h);
  drawRegion(ctx, { x, y, w, h });
  ctx.restore();
}

Animasyon karesinde sıra ve atomik görünürlük

Tek bir requestAnimationFrame turunda kullanıcıya yansıyan bitmap, teorik olarak «o anın snapshot’ı»dır — bu yüzden önce temizlik / zemin, sonra dünya geometrisi ve en sonda HUD veya imleç katmanı gibi bir sözleşme çoğu ekipte çalışır. Ara durumda yarı çizilmiş sahneyi uzun süre ekranda bırakmak isterseniz bilinçli bir hata ayıklama modu olmalıdır; üretimde yarım kare kullanıcıya görünmemelidir.

Ağır çizimleri iki aşamada düşünmek yardımcıdır: dünya durumunu güncelle ( Delta time ile entegre), ardından tek geçişte çiz — çift tampon veya offscreen yüzey kullanıyorsanız ana tuvale aktarma adımı da aynı turun sonunda tamamlanır.

Özel birleştirme geçişleri ( lighter vb.) için kısa save/restore dalları, temel zemin ve temizlikten sonra uygulanır; dal kapatılmazsa sonraki karenin temizliği beklenmedik şeffaflık bırakır.

Resize, piksel yoğunluğu ve ilk boyama

Görüntü alanı yeniden boyutlandığında dahili canvas.width / canvas.height ataması çoğu tarayıcıda içeriği sıfırlar veya tanımsız hale getirir — pratikte tam sahneyi yeniden kurmanız gerekir. Bu olay, genellikle resize sonrası ilk rAF’ta veya ResizeObserver geri çağrısında opak zemin + dünya yeniden inşası ile çözülür.

devicePixelRatio ile iç piksel boyutu artırılıyorsa temizlik ve dolgu dikdörtgeni hâlâ bağlamın width/height değerleriyle hizalanır; css pikseli ile karıştırmamak için tek doğruluk kaynağı bağlam ölçüsünü seçin ( Resize mantığı ).

İlk sayfa yüklemede bile boş canvas şeffaf olabilir; flaş önlemek için ilk boyamayı mümkün olduğunca erken veya boyut kesinleştikten hemen sonra planlayın — içerik yüklenene kadar düz renk yer tutucu yaygındır.

Anti-kalıplar: hayalet piksel ve sıra hataları

Dönüşümlü clearRect: Kimlik matrisine dönmeden tam yüzey sandığınız temizlik eksik kalır — en iyisi paylaşılan yardımcı fonksiyon kullanmak.

Kısmi temizlik + geniş hareket: İmgenin arkasında iz bırakırsınız; kirli kutu birleştirmeyi unutmayın.

clear yok, sürekli add: Bilinçli trail istemiyorsanız kare birikir; CPU ve görsel mantık bozulur.

Resize sonrası eski bitmap varsayımı: İçerik sıfırlandıktan sonra eski önbellekli görselleri çizmek hayalet sahne üretir.

Bu sayfanın sınırı

WebGL derinlik tamponu ve stencil «clear» komutları farklı API’dir; burada yalnızca CanvasRenderingContext2D bitmap temizliği ve yeniden çizim sırası anlatılmıştır.

OffscreenCanvas ve worker tarafı yüzey senkronizasyonu ayrı performans başlığıdır — bu sayfa ana belgede tek görünür canvas varsayar.

  • Temizlik kimlik matrisinde ve doğru piksel boyutunda mı?
  • Şeffaf mı opak zemin mi; CSS arka plana güveniliyor mu?
  • Kısmi temizlikte hayalet piksel için kutu birleştirildi mi?
  • Kare içinde dünya → HUD sırası atomik mi?
  • Resize veya DPR değişiminde tam yeniden kuruldu mu?