Start · Sprachen · JavaScript · Referenz · Ink

Ink

Schnittstelle

Das <code>Ink</code>-Interface der Ink API stellt über <code>navigator.ink</code> <code>DelegatedInkTrailPresenter</code>-Objekte bereit, mit denen Tintenstriche mit geringer Latenz gezeichnet werden.

seit JavaScript Experimentell: Chromium 94+ (Chrome, Edge, Opera); Kategorie: webapi

Signatur

interface Ink

Beschreibung

Das Ink-Interface ist der Einstiegspunkt der Ink API. Du erreichst es über navigator.ink. Es hat genau eine Methode, requestPresenter(). Sie gibt ein Promise zurück, das mit einem DelegatedInkTrailPresenter erfüllt wird. Über diesen Presenter übergibt die Anwendung das Zeichnen des letzten Stückchens eines Tintenstrichs an den Compositor des Betriebssystems bzw. Browsers.

Warum das nützlich ist: In Zeichen- und Notiz-Apps mit Stift oder Maus hängt der gezeichnete Strich immer ein paar Millisekunden hinter dem Zeiger her. Der Grund ist, dass jedes Frame erst durch die Rendering-Pipeline muss (JavaScript, Layout, Paint, Composite). Mit presenter.updateInkTrailStartPoint(event, style) sagst du dem Browser, bis zu welchem Punkt deine Anwendung schon gezeichnet hat. Den Rest bis zur aktuellen Zeigerposition zeichnet der Browser selbst, und zwar sofort mit den neuesten Eingabedaten. Dadurch wirkt der Strich deutlich direkter, fast wie auf Papier.

Verwende Ink nur, wenn du ein <canvas> oder ein anderes Element zum Zeichnen mit Pointer Events einsetzt. Den eigentlichen Strich zeichnest du weiterhin selbst. Der Presenter überbrückt nur die Latenz zwischen deinem letzten gezeichneten Punkt und dem Zeiger. Da die API experimentell ist, solltest du sie immer als Progressive Enhancement einbauen: vorher mit 'ink' in navigator prüfen, ob sie verfügbar ist.

Parameter

Name Typ Default Beschreibung
$requestPresenter(param) Method Einzige Methode des Interfaces. Gibt Promise<DelegatedInkTrailPresenter> zurück.
$param.presentationArea Element | null null Element (meist ein <canvas>), auf dessen Rahmen die vorhergesagte Tintenspur begrenzt wird. Bei null oder ohne Angabe gilt der Viewport des Dokuments. Das Element muss zum selben Dokument gehören, sonst wird das Promise mit einem DOMException vom Typ NotAllowedError abgelehnt.

Rückgabewert

Typ
Ink
Beschreibung
Eine Instanz liegt unter navigator.ink. Das Interface hat keinen öffentlichen Konstruktor. requestPresenter() gibt ein Promise<DelegatedInkTrailPresenter> zurück.

Beispiele

Unterstützung prüfen und Presenter anfordern

const canvas = document.querySelector('#zeichenflaeche');

const getPresenter = async () => {
  if (!('ink' in navigator)) {
    console.log('Ink API nicht verfügbar – normales Zeichnen');
    return null;
  }
  // Tintenspur auf den Bereich des Canvas begrenzen
  const presenter = await navigator.ink.requestPresenter({ presentationArea: canvas });
  console.log('Presenter bereit:', presenter.presentationArea === canvas);
  return presenter;
};

getPresenter();
Presenter bereit: true

Zeichen-App mit Tintenspur geringer Latenz

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
const style = { color: 'rgb(0, 0, 200)', diameter: 4 };
let presenter = null;
let drawing = false;

if ('ink' in navigator) {
  navigator.ink.requestPresenter({ presentationArea: canvas })
    .then((p) => { presenter = p; });
}

ctx.strokeStyle = style.color;
ctx.lineWidth = style.diameter;
ctx.lineCap = 'round';

canvas.addEventListener('pointerdown', (e) => {
  drawing = true;
  ctx.beginPath();
  ctx.moveTo(e.offsetX, e.offsetY);
});

canvas.addEventListener('pointermove', (e) => {
  if (!drawing) return;
  // Zusammengefasste Events für einen glatteren Strich
  for (const ev of e.getCoalescedEvents?.() ?? [e]) {
    ctx.lineTo(ev.offsetX, ev.offsetY);
  }
  ctx.stroke();
  // Browser zeichnet ab diesem Punkt bis zum Zeiger selbst
  presenter?.updateInkTrailStartPoint(e, style);
});

canvas.addEventListener('pointerup', () => { drawing = false; });

Fehlerbehandlung bei ungültigem Präsentationsbereich

const fremdesElement = document.createElement('iframe').ownerDocument === document
  ? document.implementation.createHTMLDocument().body
  : null;

try {
  await navigator.ink.requestPresenter({ presentationArea: fremdesElement });
} catch (err) {
  console.error(err.name);
}
NotAllowedError

// Wichtig · Fallstricke

  • Experimentell und nur in Chromium verfügbar (Chrome/Edge 94+). Firefox und Safari unterstützen die API nicht. Prüfe deshalb immer mit 'ink' in navigator und biete sonst ganz normales Zeichnen auf dem Canvas an.
  • updateInkTrailStartPoint() erwartet ein vertrauenswürdiges PointerEvent (isTrusted === true). Mit selbst erzeugten Events wirft der Aufruf einen Fehler.
  • Die Farbe in style.color muss ein gültiger CSS-Farbwert sein, und diameter muss größer als 0 sein. Sonst gibt es einen TypeError. Stimmen Farbe und Strichbreite nicht mit deinem eigenen Canvas-Strich überein, sieht man sichtbare Übergänge.
  • Die vom Browser gezeichnete Spur ist nur vorübergehend und verschwindet mit dem nächsten Frame. Den dauerhaften Strich musst du also selbst zeichnen.
  • Nur im sicheren Kontext (HTTPS) und im Hauptdokument sinnvoll. Wenn der Präsentationsbereich per CSS-Transformation gedreht oder verzerrt ist, kann die Spur verschoben erscheinen.