1. 引言
在 Web 上实现低延迟对于出色的墨迹书写体验至关重要。通常,Web 上的墨迹书写
涉及消费 PointerEvent
事件,并将笔画渲染到 canvas、
WebGL,甚至 SVG。
虽然目前已经有一些渐进增强可用,例如 getPredictedEvents()
和 Desyncronized canvas,但这些都没有利用由操作系统提供的系统合成器来实现更好的延迟。
操作系统合成器通常会引入一帧延迟,以便将所有窗口组合在一起。在这一帧延迟期间,输入可能会被传递给
应用程序,但应用程序要到下一帧才能用这个新输入来更新已渲染的帧。系统合成器可能有能力代表应用程序处理此输入,并
相应地更新当前帧。Ink API 的目的,是将系统合成器的这一功能公开给
Web 应用程序,作为一种渐进增强选项,使其在受支持的系统上能够实现与原生应用程序相当的延迟。
它不是对现有渐进式墨迹增强的替代,而是提供另一种选择。
2. 范围
3. Ink API
3.1. 引言
为了让系统合成器能够以足够高的保真度绘制后续输入点,应用程序 需要向合成器描述最后一个已渲染的点。如果系统知道最后一个已渲染的 点,它就可以为已传递给 Web 应用程序但尚未渲染的笔输入事件生成墨迹轨迹片段。例如,考虑一个已经将所有墨迹笔画渲染到当前输入帧的应用程序:

这里,笔继续在数字化仪上移动,但应用程序还没有机会处理 此输入以进行渲染。为了实现“superwet”墨迹书写体验,系统合成器需要为这些输入叠加 墨迹片段:

当 PointerEvent
被传递给 Web 应用程序时,应用程序可以无缝地用应用程序渲染的笔画替换系统合成器墨迹,并
将其渲染的最后一个事件点更新给合成器:

Ink API 提供 DelegatedInkTrailPresenter
接口,用于公开底层操作系统 API 以实现这一点,并保持可扩展性开放,
以便将来支持更多 presenter。
3.2. Ink
接口
[Exposed =Window ]interface {Ink Promise <DelegatedInkTrailPresenter >requestPresenter (optional InkPresenterParam = {}); };param
requestPresenter(param)-
此方法会在一个 Promise 中返回
DelegatedInkTrailPresenter对象的实例,该对象可用于在PointerEvent分派之间渲染墨迹笔画。每次调用此方法时,都必须创建一个新的DelegatedInkTrailPresenter实例。
3.3. InkPresenterParam
字典
dictionary {InkPresenterParam Element ?presentationArea =null ; };
presentationArea, 类型为 Element,可为空,默认值为null-
一个可选的
Element, 它将墨迹轨迹的渲染限制在该元素所限定的区域内。presentationArea 必须 为 null,或者与 Ink 接口位于同一个文档中,否则抛出错误并中止。
3.4. DelegatedInkTrailPresenter
接口
[Exposed =Window ]interface {DelegatedInkTrailPresenter readonly attribute Element ?presentationArea ;undefined updateInkTrailStartPoint (PointerEvent ,event InkTrailStyle ); };style
presentationArea, 类型为 Element,只读,可为空-
对 DOM 元素的引用,presenter 的作用域被限制到该元素,以防止在 所提供区域之外呈现墨迹。此区域始终是该元素边框盒的客户端坐标,因此 移动元素或滚动元素无需作者重新计算。如果未提供此项, 默认使用包含它的视口。此元素必须与
DelegatedInkTrailPresenter所关联的文档处于同一文档中,并且也必须与接收PointerEvent的文档相同, 否则将抛出错误。如果 presentationArea 曾从文档中移除,则下一次 updateInkTrailStartPoint 必须抛出错误并中止。
updateInkTrailStartPoint(event, style)-
此方法向 presenter 指示哪个
PointerEvent被用作当前帧的最后一个渲染点。这必须是一个受信任的事件,并且它与DelegatedInkTrailPresenter位于同一文档中。所生成的委托墨迹轨迹必须在下一个动画帧期间渲染, 然后移除。
3.5. InkTrailStyle
字典
dictionary {InkTrailStyle required DOMString color ;required unrestricted double diameter ; };
color, 类型为 DOMString-
这指定 presenter 在渲染墨迹轨迹时要使用的 CSS 颜色代码。它必须是 有效的 CSS 颜色,否则抛出错误并中止。
diameter, 类型为 unrestricted double-
这指定 presenter 在显示墨迹轨迹时应使用的直径。它必须 大于 0,否则抛出错误并中止。
3.6.
Ink Navigator 接口
扩展
此局部接口定义了对 Navigator 接口的扩展
[Exposed =Window ]partial interface Navigator { [SameObject ]readonly attribute Ink ink ; };
ink, 类型为 Ink,只读-
当前文档的
Ink实例。它必须与将包含presentationArea的文档关联,并且与将接收用于绘制的PointerEvent的文档关联。
4. 使用示例
function renderInkStroke( x, y, canvas) { // ... 将墨迹笔画渲染到 canvas ... } try { let canvas= document. querySelector( "#canvas" ); let presenter= await navigator. ink. requestPresenter({ presentationArea: canvas}); window. addEventListener( 'pointermove' , function ( event) { // 渲染所有来自事件队列的点。 let points= event. getCoalescedEvents(); points. forEach( p=> { renderInkStroke( p. x, p. y, canvas); }); // 渲染属于已分派事件的墨迹笔画 renderInkStroke( event. x, event. y, canvas); // 用最后一个已渲染的点更新 presenter,并为其提供样式 presenter. updateInkTrailStartPoint( event, { color: "#7851A9" , diameter: event. pressure* 4 }); }); }