demo · v130
delegated vs undelegated trails
The Chrome 130 change removed the expectedImprovement attribute because — quoting the chromestatus motivation — "the difference in cost to the web developer between using the expectedImprovement attribute and actually delegating the wet ink trail to the OS/Browser is minimal." This demo runs both side-by-side so you can feel the delegation win — the right pad hands the wet ink off to the OS compositor; the left does it all in JavaScript.
requires a stylus or recent Chrome desktop
Delegated Ink runs against the OS compositor — its effect is most visible on a touchscreen with a pen and a high-refresh display. On a regular mouse on a 60Hz monitor, you can still measure the timing difference in the meters below.
undelegated — JS draws every frame
last input → paint– ms
rAFs per stroke0
delegated — OS draws the wet ink
last input → JS paint– ms
delegated points queued0
the code
// 1. Get the delegated presenter (Chrome desktop only).
const ctx = canvas.getContext("2d");
const presenter = await navigator.ink.requestPresenter({ presentationArea: canvas });
canvas.addEventListener("pointermove", (ev) => {
// 2. JS keeps drawing committed strokes as before...
ctx.lineTo(ev.offsetX, ev.offsetY);
ctx.stroke();
// 3. ...then hands the "wet ink" trail forward to the compositor.
// The OS paints what's between the last committed point and where
// the pen actually is RIGHT NOW, ahead of the next JS frame.
presenter.updateInkTrailStartPoint(ev, {
color: "#000",
diameter: 4,
});
});
// The old expectedImprovement attribute is gone — measure for real with:
new PerformanceObserver((list) => {
for (const e of list.getEntries()) {
if (e.entryType === "event" && e.name.startsWith("pointer")) {
console.log("pointer →", e.processingEnd - e.startTime, "ms");
}
}
}).observe({ type: "event", buffered: true });