Web için oluşturulan ekran kalemi tabanlı çizim uygulamalarında uzun süredir gecikme sorunları yaşanıyor. Bunun nedeni, web sayfasının grafik güncellemelerini DOM ile senkronize etmesidir. Çizim uygulamalarında 50 milisaniyeden uzun gecikmeler, kullanıcının el-göz koordinasyonunu engelleyerek uygulamaların kullanımını zorlaştırabilir.
canvas.getContext()
için desynchronized
ipucu, her zamanki DOM güncelleme mekanizmasını atlayan farklı bir kod yolu çağırır.
Bunun yerine ipucu, temeldeki sisteme birleştirme işlemini mümkün olduğunca atlamasını söyler ve bazı durumlarda tuvalin temel arabelleği doğrudan ekranın ekran denetleyicisine gönderilir. Bu, oluşturucu birleştirici sırası kullanıldığında oluşabilecek gecikmeyi ortadan kaldırır.
Ne kadar iyi?
Koda ulaşmak istiyorsanız ileri kaydırın. Bunu çalışırken görmek için dokunmatik ekranlı bir cihaza ve tercihen bir ekran kalemine ihtiyacınız vardır. (Parmaklar da işe yarar.) Varsa 2d veya webgl örneklerini deneyin. Geri kalanlar için bu özelliği uygulayan mühendislerden biri olan Miguel Casas'ın hazırladığı bu demoya göz atın. Demoyu açın, oynat'a basın, ardından kaydırma çubuğunu rastgele ve hızlı bir şekilde ileri geri hareket ettirin.
Bu örnekte Blender açık film projesi olan Durian'ın Sintel adlı kısa filminden bir dakikalık, yirmi bir saniyelik bir klip kullanılmaktadır. Bu örnekte film, içeriği aynı anda bir <canvas>
öğesine oluşturulan <video>
öğesinde oynatılır. Birçok cihaz bu işlemi yırtılmadan yapabilir. Bununla birlikte, örneğin ChromeOS gibi ön arabellek oluşturma işlevi olan cihazlarda yırtılma görülebilir. (Film harika ama üzücü.
Gördükten sonra bir saat boyunca işe yaramamıştım. Kendinizi uyarılmış olarak düşünün.)
İpucunu kullanma
Düşük gecikme süresi, canvas.getContext()
uygulamasına desynchronized
eklemekten daha fazlasıdır. Sorunları tek tek ele alacağım.
Tuvali oluştur
Başka bir API'de önce özellik algılamadan bahsedeceğim. desynchronized
ipucu için önce kanvası oluşturmalısınız. canvas.getContext()
işlevini çağırın ve buna true
değeriyle 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 özellik nesnesinin desynchronized
özelliği varsa test edin.
if (ctx.getContextAttributes().desynchronized) {
console.log('Low latency canvas supported. Yay!');
} else {
console.log('Low latency canvas not supported. Boo!');
}
Titreme önleniyor
Doğru şekilde kodlamazsanız titremenize yol açabilecek iki durum vardır.
Chrome'un da dahil olduğu bazı tarayıcılar, çerçeveler arasında WebGL tuvallerini temizler. Ekran denetleyicisinin arabelleği boşken okuması mümkündür ve bu da görüntünün titremesine yol açar. 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
});
Titreme, kendi çizim kodunuzda ekran bağlamını temizlediğinizde de ortaya çıkabilir. Temizlemeniz gerekirse ekran dışı bir çerçeve arabelleğine çizin ve daha sonra bunu ekrana kopyalayın.
Alfa kanalları
Alfanın true (doğru) değerine ayarlandığı yarı saydam bir tuval öğesinin senkronizasyonu yine de kaldırılabilir ancak üzerinde başka DOM öğesi olmamalıdır.
Yalnızca bir tane olabilir
canvas.getContext()
için yapılan ilk çağrıdan sonra bağlam özelliklerini değiştiremezsiniz. Bu her zaman doğrudur, ancak farkında değilseniz veya
unu unutursanız tekrar etmek sizi hayal kırıklığına uğratabilir .
Örneğin, bir bağlam aldığımı ve alfayı false (yanlış) olarak belirttiğimi, ardından kodumun ilerleyen bölümlerinde aşağıda gösterildiği gibi alfayı true (doğru) olarak ayarlamış ikinci kez canvas.getContext()
çağırıyorum.
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
öğelerinin aynı nesne olduğu açık değil. Alfa hâlâ yanlıştır ve alfanın doğru değerine
eşit olduğu bir bağlam hiçbir zaman oluşturulmaz.
Desteklenen tuval türleri
getContext()
parametresine iletilen ilk parametre contextType
değeridir. getContext()
hakkında zaten bilginiz varsa "2d" bağlam türleri dışında herhangi bir şeyin desteklenip desteklenmediğini merak edersiniz. Aşağıdaki tabloda, desynchronized
destekleyen bağlam türleri gösterilmektedir.
contextType | Bağlam türü nesnesi |
---|---|
|
|
|
|
|
|
Sonuç
Bunun daha fazlasını görmek isterseniz örneklere göz atın. Yukarıda açıklanan video örneğine ek olarak, hem "2d" hem de 'webgl' bağlamlarını gösteren örnekler bulunmaktadır.