Start · Sprachen · JavaScript · Referenz · EditContext.characterBounds()

EditContext.characterBounds()

Methode

Gibt ein Array von <code>DOMRect</code>-Objekten zurück: die Begrenzungsrechtecke der Zeichen, die zuvor mit <code>updateCharacterBounds()</code> im <code>EditContext</code> hinterlegt wurden.

seit JavaScript Experimentell: Chrome/Edge 121+ (nicht in Firefox Kategorie: webapi

Signatur

EditContext.prototype.characterBounds()

Beschreibung

Die Methode characterBounds() der Schnittstelle EditContext liefert die Liste der Zeichen-Begrenzungsrechtecke, die das Skript zuletzt über updateCharacterBounds() gesetzt hat. Jedes DOMRect im Array beschreibt Position und Größe eines Zeichens. Das erste Element gehört zum Zeichen mit dem Index characterBoundsRangeStart.

Wichtig: Der Browser berechnet diese Rechtecke nicht selbst. Die EditContext-API ist für eigene Editoren gedacht, die ihren Text zum Beispiel in ein <canvas> zeichnen. Der Browser weiß dann nicht, wo die Zeichen auf dem Bildschirm liegen. Deshalb muss die Anwendung ihm diese Geometrie mitteilen. Das Betriebssystem braucht sie, um IME-Kandidatenfenster (z. B. für Japanisch oder Chinesisch), Bildschirmtastaturen oder Handschrifterkennung richtig zu positionieren.

Normalerweise reagiert man auf das Ereignis characterboundsupdate, berechnet die Rechtecke für den angefragten Bereich und übergibt sie mit updateCharacterBounds(). Mit characterBounds() liest man diese Werte später wieder aus, etwa zum Debuggen, zum Prüfen oder um Hervorhebungen zu zeichnen.

Rückgabewert

Typ
DOMRect[]
Beschreibung
Ein Array von DOMRect-Objekten. Es ist leer, solange noch nie updateCharacterBounds() aufgerufen wurde. Die Koordinaten sind die Werte, die die Anwendung übergeben hat, üblicherweise relativ zum Viewport (Client-Koordinaten).

Beispiele

Grundlegende Nutzung: Rechtecke setzen und auslesen

const canvas = document.querySelector('canvas');
const editContext = new EditContext({ text: 'Hallo' });
canvas.editContext = editContext;

// Anfangs gibt es noch keine Rechtecke
console.log(editContext.characterBounds().length);

// Jedes Zeichen ist 10px breit und 20px hoch
const rects = [...'Hallo'].map((_, i) => new DOMRect(10 + i * 10, 50, 10, 20));
editContext.updateCharacterBounds(0, rects);

const bounds = editContext.characterBounds();
console.log(bounds.length, bounds[1].x, editContext.characterBoundsRangeStart);
0 5 20 0

Auf characterboundsupdate reagieren (Canvas-Editor)

const canvas = document.querySelector('#editor');
const ctx = canvas.getContext('2d');
ctx.font = '16px monospace';

const editContext = new EditContext();
canvas.editContext = editContext;

editContext.addEventListener('characterboundsupdate', (event) => {
  const { rangeStart, rangeEnd } = event;
  const canvasRect = canvas.getBoundingClientRect();
  const text = editContext.text;
  const rects = [];

  for (let i = rangeStart; i < rangeEnd; i++) {
    const x = ctx.measureText(text.slice(0, i)).width;
    const w = ctx.measureText(text[i] ?? ' ').width;
    // In Viewport-Koordinaten umrechnen
    rects.push(new DOMRect(canvasRect.x + x, canvasRect.y + 4, w, 20));
  }

  editContext.updateCharacterBounds(rangeStart, rects);
  console.log('Gesetzt:', editContext.characterBounds().length, 'Rechtecke ab Index', rangeStart);
});
Gesetzt: 3 Rechtecke ab Index 2

Debug-Hilfe: hinterlegte Rechtecke als Rahmen einzeichnen

const drawDebugBounds = (canvas, editContext) => {
  const ctx = canvas.getContext('2d');
  const origin = canvas.getBoundingClientRect();
  ctx.save();
  ctx.strokeStyle = 'red';
  for (const rect of editContext.characterBounds()) {
    ctx.strokeRect(rect.x - origin.x, rect.y - origin.y, rect.width, rect.height);
  }
  ctx.restore();
};

if ('EditContext' in window) {
  const canvas = document.querySelector('canvas');
  drawDebugBounds(canvas, canvas.editContext);
}

// Wichtig · Fallstricke

  • Experimentell und nur in Chromium verfügbar: Chrome und Edge ab Version 121. Firefox und Safari unterstützen die API derzeit nicht. Vor der Nutzung mit 'EditContext' in window prüfen und eine Alternative bereitstellen, zum Beispiel ein verstecktes <textarea>.
  • Die Methode liefert nur die zuletzt gesetzten Werte und keine vom Browser gemessene Geometrie. Nach Scrollen, Größenänderung oder Textänderungen können die Werte veraltet sein. Dann erneut updateCharacterBounds() aufrufen.
  • Das erste Element im Array gehört zum Index characterBoundsRangeStart und nicht unbedingt zu Index 0. Beim Zuordnen zu Textpositionen muss dieser Versatz eingerechnet werden.
  • Der Browser prüft die Koordinaten nicht. Falsche Werte, etwa relativ zum Canvas statt zum Viewport, erzeugen keinen Fehler, aber das IME-Fenster erscheint an der falschen Stelle.
  • Jeder Aufruf von updateCharacterBounds() ersetzt die bisherige Liste vollständig. Es wird nichts angehängt.