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

EditContext.updateCharacterBounds()

Methode

Teilt dem Betriebssystem Position und Größe einzelner Zeichen im bearbeitbaren Bereich mit, meist als Reaktion auf das Ereignis <code>characterboundsupdate</code>.

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

Signatur

EditContext.prototype.updateCharacterBounds(rangeStart, characterBounds)

Beschreibung

Mit updateCharacterBounds() sagt ein Editor, der auf der EditContext-API aufbaut, dem Betriebssystem, wo genau einzelne Zeichen auf dem Bildschirm stehen. Diese Angaben braucht die Texteingabe des Systems (IME, Input Method Editor), zum Beispiel bei der Eingabe von Chinesisch, Japanisch oder Koreanisch. Nur mit ihnen erscheint das Fenster mit den Kandidaten direkt neben dem Text, der gerade zusammengesetzt wird.

Normalerweise rufst du die Methode im Handler des Ereignisses characterboundsupdate auf. Das Ereignis liefert in event.rangeStart und event.rangeEnd den Zeichenbereich, für den das System Maße anfordert. Du berechnest dann für jedes Zeichen in diesem Bereich ein DOMRect und übergibst die Liste zusammen mit dem Startindex.

Das ist vor allem dann wichtig, wenn du Text selbst zeichnest, etwa in einem <canvas>. Dort kennt der Browser die Lage der Zeichen nicht und kann sie dem System nicht selbst melden. Die Rechtecke müssen in Koordinaten relativ zum sichtbaren Bereich des Fensters (Viewport) angegeben werden, also im selben Bezugssystem wie getBoundingClientRect().

Parameter

Name Typ Default Beschreibung
$rangeStart Pflicht number Position des ersten Zeichens, für das Maße übergeben werden, gezählt ab dem Anfang von editContext.text. Meist wird event.rangeStart übernommen.
$characterBounds Pflicht Array<DOMRect> Liste mit einem DOMRect pro Zeichen, beginnend bei rangeStart. Die Koordinaten beziehen sich auf den Viewport.

Rückgabewert

Typ
undefined
Beschreibung
Kein Rückgabewert.

Beispiele

Einfacher Aufruf mit festen Zeichenbreiten

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

editContext.addEventListener('characterboundsupdate', (event) => {
  const box = editor.getBoundingClientRect();
  const charWidth = 10;  // Monospace-Annahme
  const lineHeight = 20;

  const bounds = [];
  for (let i = event.rangeStart; i < event.rangeEnd; i++) {
    bounds.push(new DOMRect(box.x + i * charWidth, box.y, charWidth, lineHeight));
  }

  editContext.updateCharacterBounds(event.rangeStart, bounds);
  console.log(`Maße für ${bounds.length} Zeichen gemeldet`);
});
Maße für 3 Zeichen gemeldet

Canvas-Editor: Zeichenbreiten mit measureText berechnen

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
ctx.font = '16px sans-serif';

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

const PADDING = 8;
const LINE_HEIGHT = 22;

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

  for (let i = rangeStart; i < rangeEnd; i++) {
    // x-Position = Breite des Textes vor dem Zeichen
    const x = ctx.measureText(text.slice(0, i)).width;
    const w = ctx.measureText(text[i] ?? '').width;
    bounds.push(new DOMRect(rect.left + PADDING + x, rect.top + PADDING, w, LINE_HEIGHT));
  }

  editContext.updateCharacterBounds(rangeStart, bounds);
});

Mit updateControlBounds und updateSelectionBounds kombinieren

const el = document.querySelector('#editor');
const editContext = new EditContext();
el.editContext = editContext;

const syncBounds = () => {
  const box = el.getBoundingClientRect();
  editContext.updateControlBounds(box);
  // Rechteck der Einfügemarke (hier vereinfacht)
  editContext.updateSelectionBounds(new DOMRect(box.x, box.y, 1, 20));
};

el.addEventListener('focus', syncBounds);
window.addEventListener('scroll', syncBounds, { passive: true });

editContext.addEventListener('characterboundsupdate', (e) => {
  const box = el.getBoundingClientRect();
  const bounds = Array.from({ length: e.rangeEnd - e.rangeStart }, (_, k) =>
    new DOMRect(box.x + (e.rangeStart + k) * 9, box.y, 9, 20)
  );
  editContext.updateCharacterBounds(e.rangeStart, bounds);
});

// Wichtig · Fallstricke

  • Experimentell: Die EditContext-API gibt es bisher nur in Chromium-Browsern (Chrome/Edge ab 121). Prüfe die Unterstützung vorher mit 'EditContext' in window und plane einen Ersatz ein, zum Beispiel contenteditable oder ein verstecktes <textarea>.
  • Die Rechtecke müssen relativ zum Viewport angegeben werden, nicht relativ zum Canvas oder zum Dokument. Wird gescrollt oder das Layout ändert sich, stimmen früher gemeldete Werte nicht mehr.
  • Pro Zeichen im angefragten Bereich wird genau ein DOMRect erwartet. Fehlen Einträge oder sind die Werte falsch, erscheint das IME-Fenster an der falschen Stelle.
  • Fehlen Argumente oder ist rangeStart keine Zahl bzw. characterBounds keine Liste von DOMRect-Objekten, wird ein TypeError ausgelöst.
  • Die Positionen beziehen sich auf die Einheiten von editContext.text (UTF-16-Codeeinheiten). Bei Emoji oder Ersatzzeichenpaaren (Surrogatpaaren) musst du die Indizes entsprechend behandeln.
  • Leistung: measureText für jede Teilzeichenkette ist bei langen Texten teuer. Speichere berechnete Positionen zwischen (Cache).