Signatur
Beschreibung
Die schreibgeschützte Eigenschaft characterBoundsRangeStart gehört zur EditContext-Schnittstelle. Sie gibt an, bei welchem Zeichen im bearbeitbaren Text die Liste der Zeichengrenzen beginnt, die mit updateCharacterBounds() übergeben wurde. Der erste DOMRect aus characterBounds() beschreibt also die Position des Zeichens mit dem Index characterBoundsRangeStart, der zweite die des nächsten Zeichens und so weiter.
Gebraucht wird das vor allem bei eigenen Editoren, die ihren Text selbst zeichnen, zum Beispiel in einem <canvas>. Das Betriebssystem und der Eingabemethoden-Editor (IME, etwa für Chinesisch oder Japanisch) müssen wissen, wo die Zeichen auf dem Bildschirm stehen. Nur dann können sie Kandidatenfenster und Unterstreichungen während der Komposition richtig platzieren. Dafür löst der Browser das Ereignis characterboundsupdate aus. Die Anwendung berechnet daraufhin die Rechtecke und meldet sie mit updateCharacterBounds(rangeStart, bounds) zurück. Den dabei übergebenen rangeStart liefert anschließend characterBoundsRangeStart.
Die Eigenschaft ist rein lesend. Ändern lässt sie sich nur über updateCharacterBounds(). Bei einem neu erzeugten EditContext ist der Wert 0.
Rückgabewert
characterBounds() gehört. Anfangswert ist 0.Beispiele
Anfangswert und Wert nach updateCharacterBounds()
const ctx = new EditContext({ text: 'Hallo Welt' });
console.log(ctx.characterBoundsRangeStart); // Anfangswert
// Zeichengrenzen für die Zeichen 6 bis 9 ("Welt") melden
const bounds = [0, 1, 2, 3].map(i => new DOMRect(60 + i * 10, 20, 10, 18));
ctx.updateCharacterBounds(6, bounds);
console.log(ctx.characterBoundsRangeStart);
console.log(ctx.characterBounds().length);
Canvas-Editor: auf characterboundsupdate reagieren
const canvas = document.querySelector('#editor');
const ctx2d = canvas.getContext('2d');
ctx2d.font = '16px monospace';
const editContext = new EditContext();
canvas.editContext = editContext;
const CHAR_WIDTH = ctx2d.measureText('M').width;
const LINE_HEIGHT = 20;
editContext.addEventListener('characterboundsupdate', (e) => {
const canvasRect = canvas.getBoundingClientRect();
const bounds = [];
for (let i = e.rangeStart; i < e.rangeEnd; i++) {
// Bildschirmkoordinaten (Viewport) für jedes Zeichen berechnen
bounds.push(new DOMRect(
canvasRect.x + i * CHAR_WIDTH,
canvasRect.y,
CHAR_WIDTH,
LINE_HEIGHT
));
}
editContext.updateCharacterBounds(e.rangeStart, bounds);
console.log('Grenzen ab Index', editContext.characterBoundsRangeStart);
});
Rechteck eines bestimmten Zeichens nachschlagen
const getCharRect = (editContext, charIndex) => {
const start = editContext.characterBoundsRangeStart;
const rects = editContext.characterBounds();
const offset = charIndex - start;
return offset >= 0 && offset < rects.length ? rects[offset] : null;
};
const ctx = new EditContext({ text: 'abcdef' });
ctx.updateCharacterBounds(2, [
new DOMRect(20, 0, 10, 18),
new DOMRect(30, 0, 10, 18)
]);
console.log(getCharRect(ctx, 3)?.x);
console.log(getCharRect(ctx, 0));
// Wichtig · Fallstricke
- Browser-Unterstützung: Die EditContext-API gibt es bisher nur in Chromium-Browsern (ab Version 121). Firefox und Safari unterstützen sie nicht. Prüfe deshalb vorher mit
'EditContext' in windowund sieh eine Ausweichlösung vor, zum Beispiel ein verstecktes<textarea>. - Die Eigenschaft ist schreibgeschützt. Eine Zuweisung wie
ctx.characterBoundsRangeStart = 5wird still ignoriert, im Strict Mode wirft sie einenTypeError. Setzen lässt sich der Wert nur überupdateCharacterBounds(). - Der Index zählt UTF-16-Codeeinheiten, keine sichtbaren Zeichen (Grapheme). Emojis oder Zeichen außerhalb der BMP belegen zwei Positionen.
- Die Rechtecke müssen in Viewport-Koordinaten angegeben werden, nicht in Canvas-Koordinaten. Sonst erscheint das IME-Kandidatenfenster an der falschen Stelle.
- Übernimm im Handler für
characterboundsupdateimmere.rangeStartals ersten Parameter. Andernfalls passencharacterBoundsRangeStartund die tatsächlich angefragten Zeichen nicht mehr zusammen.