Web için tasarlanmış, ekran kalemi tabanlı çizim uygulamaları, web sayfasının grafik güncellemelerini DOM ile senkronize etmesi gerektiğinden uzun süredir gecikme sorunlarından muzdariptir. Herhangi bir çizim uygulamasında 50 milisaniyeden uzun gecikmeler, kullanıcının el-göz koordinasyonunu etkileyerek uygulamaların kullanımını zorlaştırabilir.
canvas.getContext()
için desynchronized
ipucu, normal DOM güncelleme mekanizmasını atlayan farklı bir kod yolunu çağırır.
Bunun yerine ipucu, temel sistemden mümkün olduğunca fazla kompozisyon atlamasını ister ve bazı durumlarda kanvasın temel arabelleği doğrudan ekranın görüntü kontrolörüne gönderilir. Bu sayede, oluşturma aracısı derleyici sırasının kullanılmasından kaynaklanan gecikmeler ortadan kaldırılır.
Ne kadar iyi?
Kodu görmek için aşağı kaydırın. Bu özelliğin nasıl çalıştığını görmek için dokunmatik ekranlı bir cihaza ve tercihen bir ekran kalemine ihtiyacınız vardır. (Parmaklar da kullanılabilir.) Varsa 2d veya webgl örneklerini deneyin. Bu özelliği uygulayan mühendislerden biri olan Miguel Casas'ın bu demosuna göz atın. Demoyu açın, oynat düğmesine basın ve ardından kaydırma çubuğunu rastgele ve hızlı bir şekilde ileri geri hareket ettirin.
Bu örnekte, Blender açık film projesi Durian'ın Sintel kısa filminden bir dakika yirmi bir saniyelik bir klip kullanılmıştır. Bu örnekte, film bir <video>
öğesinde oynatılır ve içeriği aynı anda bir <canvas>
öğesinde oluşturulur. Çoğu cihaz bunu yırtılma olmadan yapabilir ancak ChromeOS gibi ön tampon oluşturma özelliğine sahip cihazlarda yırtılma olabilir. (Film harika ama kalbinizi burkuyor.
Bunu gördükten sonra bir saat boyunca hiçbir şey yapamadım. Uyarıldınız.)
İpucunu kullanma
Düşük gecikmeyi kullanmanın canvas.getContext()
'a desynchronized
eklemekten daha fazlası vardır. Sorunları tek tek ele alacağım.
Kanvası oluşturma
Başka bir API'de önce özellik algılamayı tartışırdım. desynchronized
ipucunu kullanmak için önce kanvası oluşturmanız gerekir. canvas.getContext()
işlevini çağırın ve true
değerine sahip yeni desynchronized
ipucunu iletin.
const canvas = document.querySelector('myCanvas');
const ctx = canvas.getContext('2d', {
desynchronized: true,
// Other options. See below.
});
Özellik algılama
Ardından getContextAttributes()
numaralı telefonu arayın. Döndürülen özellikler nesnesinde desynchronized
özelliği varsa bunu test edin.
if (ctx.getContextAttributes().desynchronized) {
console.log('Low latency canvas supported. Yay!');
} else {
console.log('Low latency canvas not supported. Boo!');
}
Titremeyi önleme
Kodu doğru şekilde yazmamanız durumunda titreşime neden olabilecek iki durum vardır.
Chrome da dahil olmak üzere bazı tarayıcılar, kareler arasında WebGL tuvallerini temizler. Ekran denetleyicisinin, boşken arabelleği okuması ve bunun sonucunda resmin titremesine neden olması mümkündür. Bunu önlemek için preserveDrawingBuffer
değerini true
olarak ayarlayın.
const canvas = document.querySelector('myCanvas');
const ctx = canvas.getContext('webgl', {
desynchronized: true,
preserveDrawingBuffer: true
});
Titreşim, kendi çizim kodunuzda ekran bağlamını temizlediğinizde de ortaya çıkabilir. Temizlemeniz gerekiyorsa ekran dışı bir çerçeve önbelleği çizin ve ardından bunu ekrana kopyalayın.
Alfa kanalları
Alfa değerinin doğru olarak ayarlandığı yarı saydam bir kanvas öğesi yine de senkronize edilebilir ancak üzerinde başka DOM öğeleri bulunmamalıdır.
Yalnızca bir tane
canvas.getContext()
çağrısı yapıldıktan sonra bağlam özelliklerini değiştiremezsiniz. Bu durum her zaman geçerlidir ancak bu konuyu tekrar hatırlatmak, bu konuda bilgi sahibi değilseniz veya unutmuşsanız can sıkıcı durumların önüne geçebilir .
Örneğin, bir bağlam aldığımı ve alpha değerini false olarak belirttiğimi, ardından kodumun daha ileri bir yerinde alpha değerini aşağıda gösterildiği gibi true olarak ayarlayarak canvas.getContext()
işlevini ikinci kez çağırdığımı varsayalım.
const canvas = document.querySelector('myCanvas');
const ctx1 = canvas.getContext('2d', {
alpha: false,
desynchronized: true,
});
//Some time later, in another corner of code.
const ctx2 = canvas.getContext('2d', {
alpha: true,
desynchronized: true,
});
ctx1
ve ctx2
'un aynı nesne olduğu açık değildir. Alfa değeri hâlâ yanlıştır ve alfa değeri doğru olan bir bağlam hiçbir zaman oluşturulmaz.
Desteklenen tuval türleri
getContext()
işlevine iletilen ilk parametre contextType
olur. getContext()
ile zaten aşina iseniz "2D" bağlam türleri dışında başka bir şeyin desteklenip desteklenmediğini merak ediyorsunuzdur. Aşağıdaki tabloda, desynchronized
özelliğini destekleyen bağlam türleri gösterilmektedir.
contextType | Bağlam türü nesnesi |
---|---|
|
|
|
|
|
|
Sonuç
Daha fazlasını görmek için örneklere göz atın. Daha önce açıklanan video örneğine ek olarak hem '2d' hem de 'webgl' bağlamlarını gösteren örnekler de vardır.