Op stylus gebaseerde tekentoepassingen die voor het web zijn gebouwd, hebben lange tijd last gehad van latentieproblemen omdat een webpagina grafische updates moet synchroniseren met de DOM. In elke tekentoepassing kunnen latenties langer dan 50 milliseconden de hand-oogcoördinatie van een gebruiker verstoren, waardoor toepassingen moeilijk te gebruiken worden.
De desynchronized
hint voor canvas.getContext()
roept een ander codepad aan dat het gebruikelijke DOM-updatemechanisme omzeilt. In plaats daarvan vertelt de hint het onderliggende systeem om zoveel mogelijk composities over te slaan en in sommige gevallen wordt de onderliggende buffer van het canvas rechtstreeks naar de weergavecontroller van het scherm gestuurd. Dit elimineert de latentie die zou worden veroorzaakt door het gebruik van de compositor-wachtrij van de renderer.
Hoe goed is het?
Als je de code wilt zien, scroll dan verder. Om het in actie te zien, heb je een apparaat met een touchscreen nodig, en bij voorkeur een stylus. (Vingers werken ook.) Als je er een hebt, probeer dan de 2d- of webgl -voorbeelden. Bekijk voor de rest deze demo van Miguel Casas , een van de ingenieurs die deze functie heeft geïmplementeerd. Open de demo, druk op play en beweeg de schuifregelaar willekeurig en snel heen en weer.
In dit voorbeeld wordt een fragment van één minuut en eenentwintig seconden gebruikt uit de korte film Sintel van Durian, het open filmproject van Blender. In dit voorbeeld wordt de film afgespeeld in een <video>
-element waarvan de inhoud tegelijkertijd wordt weergegeven in een <canvas>
-element. Veel apparaten kunnen dit doen zonder scheuren, hoewel apparaten met frontbufferweergave, zoals ChromeOS, mogelijk scheuren vertonen. (De film is geweldig, maar hartverscheurend. Ik was een uur nutteloos nadat ik hem had gezien. Beschouw jezelf als gewaarschuwd.)
De hint gebruiken
Er komt meer kijken bij het gebruik van lage latentie dan het toevoegen van desynchronized
aan canvas.getContext()
. Ik zal de kwesties één voor één bespreken.
Maak het canvas
Bij een andere API zou ik eerst functiedetectie bespreken. Voor de desynchronized
hint moet u eerst het canvas maken. Roep canvas.getContext()
aan en geef de nieuwe desynchronized
hint door met de waarde true
.
const canvas = document.querySelector('myCanvas');
const ctx = canvas.getContext('2d', {
desynchronized: true,
// Other options. See below.
});
Functiedetectie
Roep vervolgens getContextAttributes()
aan. Als het geretourneerde attributenobject een desynchronized
eigenschap heeft, test deze dan.
if (ctx.getContextAttributes().desynchronized) {
console.log('Low latency canvas supported. Yay!');
} else {
console.log('Low latency canvas not supported. Boo!');
}
Flikkering voorkomen
Er zijn twee gevallen waarin u flikkering kunt veroorzaken als u niet correct codeert.
Sommige browsers, waaronder Chrome, wissen WebGL-canvas tussen frames. Het is mogelijk dat de beeldschermcontroller de buffer leest terwijl deze leeg is, waardoor het getekende beeld flikkert. Om dit te voorkomen, stelt u preserveDrawingBuffer
in op true
.
const canvas = document.querySelector('myCanvas');
const ctx = canvas.getContext('webgl', {
desynchronized: true,
preserveDrawingBuffer: true
});
Flikkering kan ook optreden wanneer u de schermcontext in uw eigen tekencode wist. Als u moet wissen, teken dan naar een framebuffer buiten het scherm en kopieer die vervolgens naar het scherm.
Alfakanalen
Een doorschijnend canvaselement, waarbij alpha is ingesteld op true, kan nog steeds worden gedesynchroniseerd, maar er mogen geen andere DOM-elementen boven staan.
Er kan er maar één zijn
U kunt de contextkenmerken niet wijzigen na de eerste aanroep van canvas.getContext()
. Dit is altijd zo geweest, maar het herhalen ervan kan u enige frustratie besparen als u het niet weet of het bent vergeten.
Laten we bijvoorbeeld zeggen dat ik een context krijg en alpha specificeer als false, en ergens later in mijn code roep ik canvas.getContext()
een tweede keer aan, waarbij alpha is ingesteld op true, zoals hieronder weergegeven.
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,
});
Het is niet duidelijk dat ctx1
en ctx2
hetzelfde object zijn. Alfa is nog steeds onwaar en er wordt nooit een context gecreëerd waarbij alfa gelijk is aan waar.
Ondersteunde canvastypen
De eerste parameter die aan getContext()
wordt doorgegeven, is contextType
. Als u al bekend bent met getContext()
vraagt u zich ongetwijfeld af of er iets anders dan '2d'-contexttypen worden ondersteund. De onderstaande tabel toont de contexttypen die desynchronized
.
contextType | Contexttype-object |
---|---|
| |
| |
| |
Conclusie
Als je meer hiervan wilt zien, bekijk dan de voorbeelden. Naast het reeds beschreven videovoorbeeld zijn er voorbeelden die zowel '2d'- als 'webgl'- contexten tonen.