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

浏览器兼容性