Für das Web entwickelte Schreibanwendungen mit Eingabestift haben seit Langem Latenzprobleme, da eine Webseite Grafikaktualisierungen mit dem DOM synchronisieren muss. In jeder Zeichenanwendung können Latenzen von mehr als 50 Millisekunden die Hand-Augen-Koordination des Nutzers beeinträchtigen und die Nutzung der Anwendungen erschweren.
Der desynchronized
-Hinweis für canvas.getContext()
ruft einen anderen Codepfad auf, der den üblichen Mechanismus zur DOM-Aktualisierung umgeht.
Stattdessen weist der Hinweis das zugrunde liegende System an, so viele Zusammensetzungen wie möglich zu überspringen. In einigen Fällen wird der dem Canvas zugrunde liegende Zwischenspeicher direkt an den Anzeige-Controller des Bildschirms gesendet. Dadurch wird die Latenz beseitigt, die durch die Verwendung der Renderer-Compositor-Warteschlange verursacht würde.
Wie gut ist das?
Wenn Sie zum Code gehen möchten, scrollen Sie weiter. Um es in Aktion zu sehen, brauchst du ein Gerät mit Touchscreen und idealerweise einen Eingabestift. (Finger funktionieren auch.) Wenn Sie eines haben, versuchen Sie es mit den Beispielen für 2D oder Webgl. Die übrigen Nutzer sehen sich diese Demo von Miguel Casas an, einem der Entwickler, die diese Funktion implementiert haben. Öffnen Sie die Demo, drücken Sie die Wiedergabetaste und bewegen Sie den Schieberegler willkürlich und schnell hin und her.
Dieses Beispiel verwendet einen einminütigen, einundzwanzig Sekunden dauernden Clip aus dem Kurzfilm Sintel von Durian, dem offenen Filmprojekt Blender. In diesem Beispiel wird der Film in einem <video>
-Element wiedergegeben, dessen Inhalte gleichzeitig in einem <canvas>
-Element gerendert werden. Bei vielen Geräten ist dies ohne Tranings, auch wenn bei Geräten mit Front-Zwischenspeichern wie ChromeOS Fehler auftreten können. (Der Film ist großartig, aber schmerzhaft.
Nachdem ich es gesehen habe, war ich eine Stunde lang nutzlos. Sie gelten also gewarnt.)
Den Hinweis verwenden
Eine niedrige Latenz kann mehr genutzt werden, als desynchronized
zu canvas.getContext()
hinzuzufügen. Ich werde die Probleme einzeln durchgehen.
Canvas erstellen
Bei einer anderen API würde ich zuerst über die Funktionserkennung sprechen. Für den desynchronized
-Hinweis müssen Sie zuerst den Canvas erstellen. Rufen Sie canvas.getContext()
auf und übergeben Sie den neuen Hinweis desynchronized
mit dem Wert true
.
const canvas = document.querySelector('myCanvas');
const ctx = canvas.getContext('2d', {
desynchronized: true,
// Other options. See below.
});
Funktionserkennung
Rufen Sie als Nächstes getContextAttributes()
auf. Wenn das zurückgegebene Attributobjekt das Attribut desynchronized
hat, testen Sie es.
if (ctx.getContextAttributes().desynchronized) {
console.log('Low latency canvas supported. Yay!');
} else {
console.log('Low latency canvas not supported. Boo!');
}
Flimmern vermeiden
Es gibt zwei Fälle, in denen Sie nicht richtig programmieren können, um ein Flackern zu verursachen.
In einigen Browsern wird das WebGL-Canvas zwischen den Frames in Chrome geleert. Es ist möglich, dass der Anzeige-Controller den Zwischenspeicher liest, solange er leer ist, wodurch das gezeichnete Bild flackert. Um dies zu vermeiden, setzen Sie preserveDrawingBuffer
auf true
.
const canvas = document.querySelector('myCanvas');
const ctx = canvas.getContext('webgl', {
desynchronized: true,
preserveDrawingBuffer: true
});
Es kann auch Flackern auftreten, wenn Sie den Bildschirmkontext in Ihrem eigenen Zeichencode löschen. Wenn Sie den Inhalt löschen müssen, zeichnen Sie in einem Framebuffer außerhalb des Bildschirms und kopieren Sie diesen auf den Bildschirm.
Alphakanäle
Ein durchscheinendes Canvas-Element, bei dem Alpha auf „true“ gesetzt ist, kann zwar desynchronisiert werden, darf jedoch keine anderen DOM-Elemente darüber enthalten.
Es darf nur einen
Nach dem ersten Aufruf von canvas.getContext()
können Sie die Kontextattribute nicht mehr ändern. Das war schon immer der Fall, aber eine Wiederholung könnte Ihnen Frustration ersparen, wenn Sie es nicht wissen oder vergessen haben .
Angenommen, ich rufe einen Kontext ab und gebe „Alpha“ als „false“ an. Später in meinem Code rufe ich dann noch einmal canvas.getContext()
auf, wobei Alpha auf „true“ gesetzt ist, wie unten gezeigt.
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,
});
Es ist nicht offensichtlich, dass ctx1
und ctx2
dasselbe Objekt sind. Alpha ist immer noch falsch und ein Kontext mit Alpha gleich wahr wird nie erstellt.
Unterstützte Canvastypen
Der erste an getContext()
übergebene Parameter ist contextType
. Wenn Sie mit getContext()
bereits vertraut sind, fragen Sie sich zweifellos, ob andere Kontexttypen als „2d“-Kontexttypen unterstützt werden. Die folgende Tabelle zeigt die Kontexttypen, die desynchronized
unterstützen.
contextType | Kontexttypobjekt |
---|---|
|
|
|
|
|
|
Fazit
Wenn Sie mehr davon sehen möchten, sehen Sie sich die Beispiele an. Zusätzlich zu dem bereits beschriebenen Videobeispiel gibt es Beispiele, die sowohl den Kontext '2d' als auch 'webgl' zeigen.