1. はじめに
低レイテンシを達成することは、Web上で優れたインキング体験を実現するために重要である。一般に、Web上でのインキングは、PointerEvent
イベントを消費し、ストロークをcanvas、
WebGL、またはSVGにレンダリングすることを含む。
現在、getPredictedEvents()
やDesyncronized canvasなど、漸進的な改善は利用可能であるが、これらはいずれも、よりよいレイテンシを達成するためにオペレーティング
システムによって提供されるシステムコンポジターを活用していない。オペレーティングシステムのコンポジターは通常、すべてのウィンドウを合成するために
1フレーム分のレイテンシを導入する。このレイテンシのフレーム中、入力がアプリケーションへ届けられることはあるが、
アプリケーションは次のフレームまで、この新しい入力でレンダリング済みフレームを更新できない。システムコンポジターは、
アプリケーションに代わってこの入力を処理し、それに応じて現在のフレームを更新する能力を持つ場合がある。Ink APIの目的は、
システムコンポジターのこの機能を、対応するシステム上でネイティブアプリケーションと同等のレイテンシを達成できる
漸進的な改善オプションとしてWebアプリケーションに公開することである。これは、すでに存在する既存の漸進的インク
改善を置き換えるものではなく、別の選択肢を提供するものである。
2. スコープ
3. Ink API
3.1. はじめに
システムコンポジターが後続の入力点を十分な忠実度で描画できるようにするには、 アプリケーションが最後にレンダリングした点をコンポジターに記述する必要がある。システムが最後にレンダリングされた 点を知っていれば、Webアプリケーションに届けられたがまだレンダリングされていないペン入力イベントに対して、 インクトレイルのセグメントを生成できる。たとえば、入力の現在のフレームまでのすべてのインクストロークをレンダリングしたアプリケーションを考える:

ここで、ペンはデジタイザー上で動き続けているが、アプリケーションはこの入力をレンダリングのために処理する機会を まだ得ていない。「superwet」なインキング体験を達成するには、システムコンポジターはこれらの入力に対して インクセグメントを重ね合わせる必要がある:

PointerEvent
がWebアプリケーションに届けられると、アプリケーションはシステムコンポジターのインクを、アプリケーションがレンダリングしたストロークで
シームレスに置き換え、最後にレンダリングしたイベント点についてコンポジターを更新できる:

Ink APIは、これを達成するために基盤となるオペレーティングシステムAPIを公開するDelegatedInkTrailPresenter
インターフェイスを提供し、将来の追加プレゼンターをサポートするために拡張性を開いたままにする。
3.2. Ink
インターフェイス
[Exposed =Window ]interface {Ink Promise <DelegatedInkTrailPresenter >requestPresenter (optional InkPresenterParam = {}); };param
requestPresenter(param)-
このメソッドは、
DelegatedInkTrailPresenterオブジェクトのインスタンスをPromise内で返す。これはPointerEventのディスパッチの合間にインクストロークをレンダリングするために使用できる。このメソッドが呼び出されるたびに、新しいDelegatedInkTrailPresenterインスタンスを作成しなければならない。
3.3. InkPresenterParam
辞書
dictionary {InkPresenterParam Element ?presentationArea =null ; };
presentationArea, 型はElement、nullable、既定値はnull-
インクトレイルのレンダリングを、その要素によって境界づけられた領域に制限する任意の
Element。 presentationAreaはnullであるか、Inkインターフェイスと同じ文書内になければならない。そうでない場合はエラーを投げて中止する。
3.4. DelegatedInkTrailPresenter
インターフェイス
[Exposed =Window ]interface {DelegatedInkTrailPresenter readonly attribute Element ?presentationArea ;undefined updateInkTrailStartPoint (PointerEvent ,event InkTrailStyle ); };style
presentationArea, 型は Element、readonly、nullable-
提供された領域の外でインクが提示されることを防ぐために、プレゼンターのスコープとなるDOM要素への参照。 この領域は常に要素のボーダーボックスのクライアント座標であるため、 要素を移動したり要素をスクロールしたりしても、作者側で再計算する必要はない。 これが提供されない場合、既定では包含ビューポートを使用する。この要素は、
DelegatedInkTrailPresenterが関連付けられているものと同じ文書内にあり、かつPointerEventを受け取っている同じ文書内に なければならない。そうでない場合はエラーが投げられる。presentationAreaが文書から削除された場合、次の updateInkTrailStartPointはエラーを投げて中止しなければならない。
updateInkTrailStartPoint(event, style)-
このメソッドは、現在のフレームに対する最後のレンダリング点としてどの
PointerEventが使用されたかをプレゼンターに示す。これは、DelegatedInkTrailPresenterと同じ文書内にある信頼されたイベントでなければならない。 生成された委任インクトレイルは、次のアニメーションフレームの期間中レンダリングされ、その後削除されなければならない。
3.5. InkTrailStyle
辞書
dictionary {InkTrailStyle required DOMString color ;required unrestricted double diameter ; };
color, 型はDOMString-
これは、インクトレイルをレンダリングするときにプレゼンターが使用するCSSカラーコードを指定する。 有効なCSS色でなければならず、そうでない場合はエラーを投げて中止する。
diameter, 型はunrestricted double-
これは、インクトレイルを表示するときにプレゼンターが使用する直径を指定する。0より大きく なければならず、そうでない場合はエラーを投げて中止する。
3.6.
Ink Navigator インターフェイス
拡張
このpartialインターフェイスは、Navigatorインターフェイスへの拡張を定義する
[Exposed =Window ]partial interface Navigator { [SameObject ]readonly attribute Ink ink ; };
ink, 型はInk、readonly-
現在の文書に対する
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. updateInkTrailStartPoint( event, { color: "#7851A9" , diameter: event. pressure* 4 }); }); }