以觸控筆為基礎的繪圖應用程式在網頁上建構時,一直會遇到延遲問題,因為網頁必須將圖形更新內容與 DOM 同步。在任何繪圖應用程式中,延遲時間超過 50 毫秒可能會影響使用者的手眼協調能力,導致應用程式難以使用。
canvas.getContext()
的 desynchronized
提示會叫用不同的程式碼路徑,以便略過一般 DOM 更新機制。相反地,提示會告知底層系統盡可能略過合成作業,在某些情況下,畫布的底層緩衝區會直接傳送至螢幕的顯示控制器。這可消除使用轉譯器合成器佇列所造成的延遲。
評價如何?
如要查看程式碼,請向下捲動。如要實際操作,您需要使用具備觸控螢幕的裝置,最好還要搭配觸控筆。(手指也適用)。如果有,請試試 2D 或 WebGL 範例。其他人請參閱 Miguel Casas 的示範影片,他是實作這項功能的工程師之一。開啟示範內容,按下播放鍵,然後快速隨機移動滑桿。
這個範例使用了 Blender 開放式電影專案 Durian 的短片「Sintel」Sintel中,長度為一分二十一秒的短片片段。在這個範例中,電影會在 <video>
元素中播放,而該元素的內容會同時算繪至 <canvas>
元素。許多裝置都能在不撕裂的情況下執行此操作,但具備前緩衝區轉譯功能的裝置 (例如 ChromeOS) 可能會出現撕裂情形。(這部電影很棒,但很令人心碎。看到這則訊息後,我花了一個小時才恢復正常。隨便你。)
使用提示
使用低延遲時間的做法不只限於將 desynchronized
新增至 canvas.getContext()
。我會逐一檢查問題。
建立畫布
在另一個 API 上,我會先討論功能偵測。對於 desynchronized
提示,您必須先建立畫布。呼叫 canvas.getContext()
,並傳遞新的 desynchronized
提示,其值為 true
。
const canvas = document.querySelector('myCanvas');
const ctx = canvas.getContext('2d', {
desynchronized: true,
// Other options. See below.
});
特徵偵測
接著,呼叫 getContextAttributes()
。如果傳回的屬性物件具有 desynchronized
屬性,請測試該屬性。
if (ctx.getContextAttributes().desynchronized) {
console.log('Low latency canvas supported. Yay!');
} else {
console.log('Low latency canvas not supported. Boo!');
}
避免閃爍
如果程式碼編寫不正確,可能會導致閃爍現象。
部分瀏覽器 (包括 Chrome) 會在影格之間清除 WebGL 畫布。顯示控制器可能會在緩衝區空白時讀取緩衝區,導致繪製的圖片閃爍。如要避免這種情況,請將 preserveDrawingBuffer
設為 true
。
const canvas = document.querySelector('myCanvas');
const ctx = canvas.getContext('webgl', {
desynchronized: true,
preserveDrawingBuffer: true
});
在您自己的繪圖程式碼中清除螢幕內容時,也會發生閃爍現象。如果您必須清除,請繪製至螢幕外幀格緩衝區,然後將其複製到螢幕上。
Alpha 通道
半透明的畫布元素 (alpha 設為 true) 仍可解除同步,但不得在其上方放置任何其他 DOM 元素。
只能有一個
您無法在第一次呼叫 canvas.getContext()
後變更內容參照屬性。這一直都是事實,但如果您不清楚或忘記,重複說明可能會讓您少點挫折。
舉例來說,假設我取得了內容,並將 alpha 指定為 false,然後在程式碼的後面某處,我會再次呼叫 canvas.getContext()
,並將 alpha 設為 true,如下所示。
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
和 ctx2
是否為相同物件並不明顯。Alpha 仍為 false,且系統不會建立 alpha 等於 true 的內容。
支援的無框畫類型
傳遞至 getContext()
的第一個參數是 contextType
。如果您已熟悉 getContext()
,那麼您一定會想知道除了「2d」之外,是否還有其他支援的內容類型。下表列出支援 desynchronized
的內容類型。
contextType | 背景資訊類型物件 |
---|---|
|
|
|
|
|
|