Ink API

可用性有限

此特性不是基線特性,因為它在一些最廣泛使用的瀏覽器中不起作用。

實驗性: 這是一項實驗性技術
在生產中使用此技術之前,請仔細檢查瀏覽器相容性表格

Ink API 允許瀏覽器在繪製墨跡應用程式功能的筆觸時,直接利用作業系統級別的合成器,從而降低延遲並提高效能。

概念與用法

Web 上的墨跡繪製是指使用 指標事件繪製平滑筆觸的應用功能,例如繪圖應用程式或文件簽名功能。

指標事件通常首先發送到瀏覽器程序,然後瀏覽器程序將這些事件轉發到 JavaScript 事件迴圈,以執行關聯的處理函式並將結果渲染到應用程式中。此過程的開始和結束之間的時間延遲可能很大,導致使用者開始繪製(例如,使用手寫筆或滑鼠)與筆觸顯示在螢幕上之間存在延遲。

Ink API 透過允許瀏覽器完全繞過 JavaScript 事件迴圈來顯著降低此延遲。在可能的情況下,瀏覽器會將此類渲染指令直接傳遞給作業系統級別的合成器。如果底層作業系統沒有專門的作業系統級別合成器可用於此目的,瀏覽器將使用自己的最佳化渲染程式碼。這不如合成器功能強大,但仍然可以帶來一些改進。

注意: 合成器是渲染引擎的一部分,負責在瀏覽器或作業系統中將 UI 繪製到螢幕上。有關合成器在 Web 瀏覽器中如何工作的有趣見解,請參閱 深入瞭解現代 Web 瀏覽器(第三部分)

入口點是 Navigator.ink 屬性,它返回當前文件的 Ink 物件。 Ink.requestPresenter() 方法返回一個 Promise,該 Promise 會以 DelegatedInkTrailPresenter 物件例項 fulfilled。這指示作業系統級別的合成器在每次指標事件分派之間在下一個可用幀中渲染墨跡筆觸。

介面

Ink 實驗性

提供對 DelegatedInkTrailPresenter 物件的訪問,供應用程式用於渲染筆觸。

DelegatedInkTrailPresenter 實驗性

指示作業系統級別的合成器在指標事件分派之間渲染墨跡筆觸。

其他介面的擴充套件

返回當前文件的 Ink 物件。

示例

繪製墨跡軌跡

在此示例中,我們在 2D 畫布上繪製軌跡。在程式碼的開頭附近,我們呼叫 Ink.requestPresenter(),將畫布作為其要處理的演示區域傳遞,並將返回的 Promise 儲存在 presenter 變數中。

稍後,在 pointermove 事件監聽器中,每次事件觸發時,軌跡的新位置都會繪製到畫布上。此外,當 presenter Promise fulfilled 時返回的 DelegatedInkTrailPresenter 物件會呼叫其 updateInkTrailStartPoint() 方法;將其傳遞給

  • 表示當前幀渲染點的最後一個受信任的指標事件。
  • 一個包含顏色和直徑設定的 style 物件。

結果是,一個委託的墨跡軌跡在應用程式的預設瀏覽器渲染之前繪製,使用指定的樣式,直到下次接收到 pointermove 事件為止。

HTML

html
<canvas id="canvas"></canvas>
<div id="div">Delegated ink trail should match the color of this div.</div>

CSS

css
div {
  background-color: lime;
  position: fixed;
  top: 1rem;
  left: 1rem;
}

JavaScript

js
const ctx = canvas.getContext("2d");
const presenter = navigator.ink.requestPresenter({ presentationArea: canvas });
let move_cnt = 0;
let style = { color: "lime", diameter: 10 };

function getRandomInt(min, max) {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

canvas.addEventListener("pointermove", async (evt) => {
  const pointSize = 10;
  ctx.fillStyle = style.color;
  ctx.fillRect(evt.pageX, evt.pageY, pointSize, pointSize);
  if (move_cnt === 20) {
    const r = getRandomInt(0, 255);
    const g = getRandomInt(0, 255);
    const b = getRandomInt(0, 255);

    style = { color: `rgb(${r} ${g} ${b} / 100%)`, diameter: 10 };
    move_cnt = 0;
    document.getElementById("div").style.backgroundColor =
      `rgb(${r} ${g} ${b} / 60%)`;
  }
  move_cnt += 1;
  (await presenter).updateInkTrailStartPoint(evt, style);
});

window.addEventListener("pointerdown", () => {
  ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
});

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

結果

規範

規範
Ink API
# ink-interface

瀏覽器相容性