HTML5 Canvas · Sprite ve varlık sistemi
Resim yükleme: Canvas 2D için Image nesnesi ve ön yükleme
drawImage çağrısı, elinizde hazır bir piksel kaynağı (
HTMLImageElement, video karesi veya başka bir tuval ) olduğunda anlam
kazanır;
tarayıcıdaki raster dosyalar çoğu zaman ağdan asenkron gelir. Bu sayfa
yükleme–çizim sırasını, decode ile boyutların ne zaman güvenilir olduğunu ve dış
kaynaklarda CORS ayarının tuvali «kirletmeden» nasıl korunacağını Canvas
bakış açısıyla sabitler. Sprite dilimleme ve animasyon
Sprite levhaları ile
Kare animasyonu başlıklarında;
önbellek stratejileri
Varlık önbellekleme ile derinleşir.
Tuval yaşam döngüsü ve çizim alışkanlıkları için Temizle ve yeniden çiz, Kare yönetimi ile birlikte düşünün; bağlam girişi 2D bağlam sayfasına bağlanır.
Özet: rasterın yolu
| Adım | Amaç | Dikkat |
|---|---|---|
| Kaynak URL | Dosya veya veri URI | CORS ihtiyacını erken belirleyin |
Image + olay |
Yüklemeyi asenkron tamamlayın | onload öncesi drawImage yok |
decode() |
Boyut / piksel hazır | Eski tarayıcıda yok; yedek: onload |
drawImage |
Tuvalde gösterim | complete ve ölçek argümanları |
| Önbellek | Tekrar istekleri azalt | Önbellekleme sayfası |
Görüntü ve tuval: drawImage öncesi hazırlık
CanvasRenderingContext2D.drawImage aşırı yüklenmiş bir ailedir; raster
dosya için en yaygın yol new Image() (
document.createElement("img") eşdeğeri ) oluşturup src atamaktır.
Atama anında istek başlar; görüntü hazır olana kadar genişlik / yükseklik sıfır veya eski
değerde kalabilir — yerleşim hesabını onload veya
decode sonrasına bırakmak düzeni korur.
Kısa döngülerde «her karede yeni Image» üretmek bellek ve ağ israfıdır; sprite
tabanlı oyunda kimlik → görüntü eşlemesi tek sefer yüklenir ve oyun boyunca elde tutulur.
Tek tuval prototiplerinde bile küçük bir Map veya nesne sözlüğü düzen getirir.
Çizim kodu yalnız hazır görselleri tüketir; yükleyici katmanı ayrı dosyada tutmak test
yazımını kolaylaştırır.
naturalWidth / naturalHeight piksel cinsinden kaynak boyutunu
verir; CSS ile sayfada küçültülmüş olsa bile çizimde orijinal çözünürlük üzerinden karar
verirsiniz. Tuvalde ölçek (
9 dilim, geri uyumlu büyütme ) başka başlıkların konusudur; burada yalnız hazır pikselin
varlığı işlenir.
Asenkron yükleme: olaylar ve Promise sarımı
Klasik model: onload ve onerror geri çağrıları; modern akışta
aynı mantık Promise ile sarılır ve async/await ile okunur.
src atandıktan sonra aynı nesneye tekrar farklı src vermek yeni
istek başlatır — önbellek isabeti olsa bile olay sırasını karıştırmamak için üretimde tek
nesne–tek URL disiplini veya yükleme kimliği (
sayaç ) kullanılır.
fetch ile Blob alıp createObjectURL üretmek
mümkündür;
bu sayfada yalın Image yolu tercih edilir çünkü tarayıcı önbelleği ve sıralama
ile
iyi çalışır. İleri senaryolar (
Service Worker, parça parça indirme ) burada açılmaz.
Birden çok görüntü için Promise.all «hepsi veya hiçbiri» verir; kısmi başarı
istiyorsanız allSettled ve harita bazında hata toplama daha güvenlidir. Oyun
başlangıcında kritik set (
arayüz atlası ) ile isteğe bağlı set (
dekor ) ayırmak yükleme deneyimini yumuşatır.
/**
* crossOrigin: örn. "anonymous" — src'den ÖNCE atanmalı (export güvenli tuval için).
* Güvenilmeyen URL'lere bağlanmayın; kullanıcı girdisini doğrudan src yapmayın.
*/
function loadImage(src, { crossOrigin } = {}) {
return new Promise((resolve, reject) => {
const img = new Image();
if (crossOrigin) img.crossOrigin = crossOrigin;
img.onload = () => resolve(img);
img.onerror = () => reject(new Error("Image load failed"));
img.src = src;
});
}
Decode ve boyut: ne zaman çizmek güvenli
HTMLImageElement.decode() görüntünün asenkron olarak piksele çözülmesini
bekler;
bazı tarayıcılarda onload sonrasında bile ilk karede boş çizim görülmesini
azaltır. Destek yoksa yedek olarak yalnız onload yeterlidir — özellik çağrısını
özellik algılama ile sarın.
Oyun döngüsünde «yükleniyor» durumunda boş bir yer tutucu ( renk blok veya düşük çözünürlüklü önizleme ) çizmek kullanıcıya geri bildirim verir; metin tabanlı hata yerine üretimde günlük ve sayaç tercih edilir. Animasyonlu yükleme çubuğu Canvas veya DOM; burada mesele rasterın hazır olduğu ana kadar ana spriteları çizmemektir.
Çok büyük dokular mobilde bellek baskısı yaratır; çözünürlük seçimi ve sıkıştırma formatı ( PNG şeffaflık, WebP / AVIF desteği ) yükleme katmanından önce tasarım kararıdır — bu sayfa format savaşını işlemez, yalnız hazır olduktan sonra çizimi ele alır.
async function loadImageDecoded(src, opts) {
const img = await loadImage(src, opts);
if (typeof img.decode === "function") {
try {
await img.decode();
} catch {
/* bazı bozuk dosyalarda decode hata verebilir; onload ile yine de elde tutuldu */
}
}
return img;
}
Kaynak güvenliği ve CORS: kirlenmiş tuval
Başka kökten (
cross-origin ) yüklenen görüntü, crossOrigin
özelliği uygun ayarlanmadıysa tuvali kirletir (
tainted ); bu durumda getImageData,
toDataURL
ve benzeri okuma işlemleri güvenlik nedeniyle hata verir veya boş veri döner. Aynı kök veya
veri URL'leri genelde sorunsuzdur; harici CDN kullanıyorsanız CDN'in
CORS başlıkları ve sizin crossOrigin = "anonymous"
sırası kritiktir — önce crossOrigin, sonra
src.
Kullanıcıdan gelen rastgele URL'leri yüklemek (
açık uçlu ) güvenlik ve gizlilik riski taşır; eğitim kodunda bile sabit liste veya sunucu
ara köprüsü tercih edin. Örnek fonksiyon güvenilmeyen girdiyi src yapmaz;
çağıran kod beyaz liste uygulamalıdır.
Ekran görüntüsü veya kayıt özelliği geliştiriyorsanız kirlenme kuralını baştan bilirsiniz; yalnız görüntüleme yeterliyse ve piksel okumayacaksanız CORS ihtiyacı düşebilir — ürün hedefinize göre mimari seçin ve tek dokümanda kararları sabitleyin.
Toplu yükleme: anahtarlı atlas ve sıra politikası
Seviye başına onlarca küçük dosya yerine tek sprite levhası (
levha sayfası ) çoğu zaman daha az
istek sayısı verir; yine de levha yüklemesi de asenkron kalır. Yükleme haritası: dize
kimliği →
URL; tamamlanınca Map doldurulur. Büyük projelerde istekleri önceliklendirin (
oyuncu önce, dekor sonra ).
Promise.all bir dosya düşerse tüm zinciri reddeder; giriş ekranında «kritik
paket» için katı, arka planda «gevşek» toplama için ayrı yol ayrımı yapılabilir. Hata
mesajını kullanıcıya kopyalanabilir kod veya kısa kimlikle göstermek destek sürecini
hızlandırır.
Yükleme sırasında tuvali zorla sürekli yeniden çizmek ( her olayda tam sahne ) pil tüketir; «hazır olan kadarını çiz» veya düşük frekanslı ilerleme güncellemesi yeterlidir — kare yönetimi ile uyumludur.
/** entries: [["player","/a.png"],["ground","/b.png"]] — kritik yol için all yerine allSettled düşünün. */
async function preloadDecodedImages(entries, opts) {
const map = new Map();
const jobs = entries.map(async ([key, src]) => {
const img = await loadImageDecoded(src, opts);
map.set(key, img);
});
await Promise.all(jobs);
return map;
}
Tekilleştirme ve önbellek katmanı: tekrar yüklemeyi engelle
Aynı URL için ikinci kez new Image() üretmek gereksizdir; modül düzeyinde
Map (
url → Promise veya
HTMLImageElement ) tutmak tekilleştirme sağlar. İnce taneli içerik
güncellemesinde sürüm sorgu parametresi (
?v=2 ) önbellek kırmak için kullanılır —
Varlık önbellekleme sayfasına
bırakılan stratejilerle uyumludur.
Tarayıcı önbelleği dosyayı tutsa bile JavaScript tarafında çift yükleme yine bellekte çift görüntü oluşturabilir; tekilleştirme hem ağ hem RAM tasarrufu verir. İşçi iş parçacığı ( Worker ) içinde görüntü yükleme sınırları vardır; ana iş parçacığı modeli bu sayfanın varsayımıdır.
Büyük levhalarda «lazy» dilim çözümü ( sadece görünen bölgeler ) ileri optimizasyondur; temel sprite yüklemesinde tüm levha bir kez gelir, dilimleme koordinatları başka başlıkta uygulanır — sınırları karıştırmayın.
Hata ve düşüş: kullanıcı geri bildirimi
Ağ kesintisi, 404 ve bozuk görüntü dosyası onerror ile sinyallenir;
yakalanmayan
vaat reddi konsolu kirletir ve sessiz başarısızlık yaratır. Yükleme sarmalayıcılarında
try/catch, günlük ve kullanıcıya «yeniden dene» düğmesi minimal bir ürün
kaplamasıdır. Geliştirme ortamında eksik dosya en sık hatadır; üretimde CDN bölgesel
kesintisi.
Kısmi başarı senaryosunda eksik görseller için düşük çözünürlüklü yedek veya düz renk sprite atanması oyunun tamamen kilitlenmesini önler; hangi varlığın kritik olduğunu tasarım belgeleriyle eşleştirin.
Erişilebilirlik: yalnız Canvas kullanıyorsanız ekran okuyucu için DOM'da kısa durum metni veya ARIA canlı bölge düşünmek, yükleme hatalarında da geçerlidir — görüntü yüklemesi teknik bir ayrıntıdır, ürün deneyimi değildir.
Anti-kalıplar: erken çizim ve yanlış CORS sırası
Aşağıdaki dört örnek, Canvas prototiplerinde sık görülür; çoğu ya ilk karede boş sprite ya da üretimde kirlenmiş tuval ve gereksiz ağ trafiği olarak geri döner. Çözümler bu sayfada zaten verilen sıra ve tekilleştirme disiplinine indirgenir — yeni kütüphane öğrenmeden düzeltilir.
drawImage hemen src sonrası: Tarayıcı isteği
başlatır ama piksel henüz hazır olmayabilir; naturalWidth sıfır kalabilir veya
ara durumda eski içerik görülebilir. Güvenilir yol: onload / Promise tamamı ve
mümkünse
decode sonrası çizim —
yüklenene kadar yer tutucu çizmek (
hata ve düşüş ) kabul edilebilir bir ürün
kararıdır.
crossOrigin src’den sonra: Özellik atanınca bazı
tarayıcılar isteği yeniden yorumlamaz; sonuç kirlenmiş (
tainted ) tuval olur ve
getImageData /
toDataURL güvenilir olmaz. Kalıcı kural:
önce
crossOrigin, sonra src — aynı dosyayı yeniden yüklemek
gerekebilir.
Her kare yeni Image: Nesne başına bellek ve olay maliyeti
vardır; tarayıcı önbelleği dosyayı saklasa bile ortamda çift
HTMLImageElement tutmak RAM’i şişirir. Tek URL için tek nesne veya
«URL → Promise» eşlemesi (
tekilleştirme ) ile aynı sprite her karede
yeniden drawImage edilir, yeniden yüklenmez.
Kullanıcı metnini doğrudan src yapmak: Form veya adres çubuğu
girdisi beyaz liste veya sunucu tarafı çözümlemeden tuvala bağlanmamalı; kötü niyetli
yönlendirme
ve iz sürme riski doğar. Bu sayfa sabit URL veya güvendiğiniz CDN varsayar; dinamik
listelerde
kaynak doğrulaması yükleme katmanının dışında değil, onun önünde durmalıdır.
Bu sayfanın sınırı
WebGL dokuları, video akışı kareleri ve gelişmiş görüntü kod
çözücü
boru hatları burada işlenmez. Odak: Canvas 2D drawImage için güvenli ve
sıra
bilincinde raster yüklemedir.
- Yükleme tamamlanmadan sahne sprite çizilmiyor mu?
- Piksel okuma gerekiyorsa CORS sırası doğru mu?
- Aynı URL tekrar tekrar yüklenmiyor mu?
- Hatalı dosyalar yakalanıp kullanıcıya bildiriliyor mu?
- Büyük levha yükü için bellek bütçesi düşünüldü mü?