
Aplikacje do rysowania za pomocą rysika stworzone na potrzeby internetu od dawna mają problemy z opóźnieniami, ponieważ strona internetowa musi synchronizować aktualizacje grafiki z DOM. W przypadku każdej aplikacji do rysowania opóźnienia dłuższe niż 50 ms mogą zakłócać koordynację wzrokowo-ruchową użytkownika, przez co aplikacja staje się trudna w użyciu.
Wskazówka desynchronized
dla canvas.getContext()
wywołuje inną ścieżkę kodu, która omija standardowy mechanizm aktualizacji DOM.
Zamiast tego podpowiedź informuje podstawowy system, aby pomijał jak najwięcej operacji kompozytowania, a w niektórych przypadkach bufor podrzędny kanwy jest wysyłany bezpośrednio do kontrolera wyświetlania ekranu. Pozwala to wyeliminować opóźnienia, które mogłyby wystąpić z powodu korzystania z kolejki kompozytora.
Jak oceniasz ten produkt?

Jeśli chcesz przejść do kodu, przewiń w dół. Aby zobaczyć, jak to działa, potrzebujesz urządzenia z ekranem dotykowym i najlepiej rysika. (palce też się nadają). Jeśli masz taką kamerę, wypróbuj przykłady 2D lub WebGL. Pozostali użytkownicy mogą obejrzeć prezentację Miguela Casasa, jednego z inżynierów, którzy wprowadzili tę funkcję. Otwórz wersję demonstracyjną, naciśnij przycisk odtwarzania, a potem przesuwaj suwak losowo i szybko w obu kierunkach.
W tym przykładzie użyto klipu o długości 1 minuta i 21 sekund z krótkiego filmu Sintel autorstwa Duriana, który jest projektem filmowym w ramach otwartego projektu Blender. W tym przykładzie film jest odtwarzany w elemencie <video>
, którego zawartość jest jednocześnie renderowana do elementu <canvas>
. Wiele urządzeń może to zrobić bez rozrywania obrazu, ale urządzenia z renderowaniem w buforze wejściowym, takie jak ChromeOS, mogą mieć problemy z rozrywaniem. (Film jest świetny, ale łamie serce.
Po obejrzeniu filmu przez godzinę nie byłem w stanie nic robić. Tylko nie mów później, że nie ostrzegałem.)
Korzystanie z podpowiedzi
Korzystanie z niskiego opóźnienia to coś więcej niż dodanie desynchronized
do canvas.getContext()
. Omówię po kolei wszystkie problemy.
Tworzenie obszaru roboczego
W przypadku innego interfejsu API najpierw omówię wykrywanie funkcji. W przypadku podpowiedzi desynchronized
musisz najpierw utworzyć kartę. Wywołaj funkcję canvas.getContext()
i podaj jej nowy podpowiedź desynchronized
o wartości true
.
const canvas = document.querySelector('myCanvas');
const ctx = canvas.getContext('2d', {
desynchronized: true,
// Other options. See below.
});
Wykrywanie cech
Następnie zadzwoń pod numer getContextAttributes()
. Jeśli zwrócony obiekt atrybutów ma właściwość desynchronized
, przetestuj ją.
if (ctx.getContextAttributes().desynchronized) {
console.log('Low latency canvas supported. Yay!');
} else {
console.log('Low latency canvas not supported. Boo!');
}
Unikanie migotania
Jeśli kod nie jest prawidłowo napisany, może to spowodować migotanie.
Niektóre przeglądarki, w tym Chrome, oczyszczają płótna WebGL między klatkami. Sterownik wyświetlacza może odczytać pusty bufor, co spowoduje migotanie wyświetlanego obrazu. Aby tego uniknąć, ustaw preserveDrawingBuffer
jako true
.
const canvas = document.querySelector('myCanvas');
const ctx = canvas.getContext('webgl', {
desynchronized: true,
preserveDrawingBuffer: true
});
Migotanie może też wystąpić, gdy w kodze rysunku usuniesz kontekst ekranu. Jeśli musisz wyczyścić, narysuj na ekranie offscreen framebuffer, a potem skopiuj go na ekran.
Kanały alfa
Prześwitujący element obrazu, w którym parametr alpha ma wartość true, może być nadal rozsynchronizowany, ale nie może mieć nad sobą żadnych innych elementów DOM.
Może być tylko jeden
Po pierwszym wywołaniu funkcji canvas.getContext()
nie możesz zmieniać atrybutów kontekstu. To zawsze było prawdą, ale powtórzenie tego może oszczędzić Ci rozczarowanie, jeśli nie wiesz o tym lub zapomniałeś .
Załóżmy, że otrzymuję kontekst i określam, że alpha ma wartość false, a potem gdzieś w kodzie wywołuję funkcję canvas.getContext()
po raz drugi, przy czym ustawiam wartość alpha na true, jak pokazano poniżej.
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,
});
Nie jest oczywiste, że ctx1
i ctx2
to ten sam obiekt. Wartość alpha nadal jest ustawiona na fałsz, a kontekst z wartością alpha równą prawda nigdy nie jest tworzony.
Obsługiwane typy odbitek na płótnie
Pierwszy parametr przekazywany do funkcji getContext()
to contextType
. Jeśli znasz już getContext()
, pewnie zastanawiasz się, czy obsługiwane są inne typy kontekstu niż „2D”. Tabela poniżej zawiera typy kontekstu, które obsługują desynchronized
.
contextType | Obiekt typu kontekstu |
---|---|
|
|
|
|
|
|
Podsumowanie
Jeśli chcesz zobaczyć więcej takich przykładów, zapoznaj się z przykładami. Oprócz przykładu filmu, który został już opisany, znajdziesz tu przykłady obrazów w kontekście 2D i WebGL.