Start · Sprachen · JavaScript · Referenz · SVGTextContentElement

SVGTextContentElement

Schnittstelle

Basis-Interface für SVG-Elemente mit Textinhalt (<code>&lt;text&gt;</code>, <code>&lt;tspan&gt;</code>, <code>&lt;textPath&gt;</code>). Es bietet Methoden, um Text zu vermessen und einzelne Zeichen anzusteuern.

seit JavaScript Baseline: alle Browser Kategorie: webapi

Signatur

interface SVGTextContentElement extends SVGGraphicsElement

Beschreibung

SVGTextContentElement ist ein abstraktes Interface. Es wird von allen SVG-Elementen implementiert, die Kind-Textinhalte rendern, also von SVGTextElement, SVGTSpanElement und SVGTextPathElement. Direkt instanziieren kann man es nicht. Man erhält es über document.createElementNS() oder über einen DOM-Zugriff auf ein vorhandenes Textelement.

Das Interface ist vor allem zum Vermessen von Text gedacht. Damit lassen sich Beschriftungen in Diagrammen zentrieren, Text vor dem Rendern kürzen, Hintergrundboxen passgenau zeichnen oder Positionen einzelner Zeichen bestimmen, etwa für Animationen und Hervorhebungen.

  • Eigenschaften: textLength (SVGAnimatedLength, die gewünschte Textlänge), lengthAdjust (SVGAnimatedEnumeration: LENGTHADJUST_SPACING = 1 oder LENGTHADJUST_SPACINGANDGLYPHS = 2).
  • Methoden: getNumberOfChars(), getComputedTextLength(), getSubStringLength(charnum, nchars), getStartPositionOfChar(charnum), getEndPositionOfChar(charnum), getExtentOfChar(charnum), getRotationOfChar(charnum), getCharNumAtPosition(point) und selectSubString(charnum, nchars) (veraltet).

Alle Messmethoden liefern Werte im Benutzerkoordinatensystem des Elements. Transformationen der Eltern-Elemente fließen also nicht ein. Außerdem geben sie nur dann sinnvolle Werte zurück, wenn das Element im Dokument hängt und gerendert wird.

Parameter

Name Typ Default Beschreibung
$charnum Pflicht number Index des Zeichens (in UTF-16-Codeeinheiten), beginnend bei 0. Wird von getStartPositionOfChar(), getEndPositionOfChar(), getExtentOfChar(), getRotationOfChar() und getSubStringLength() verwendet.
$nchars Pflicht number Anzahl der Zeichen ab charnum, bei getSubStringLength() und selectSubString().
$point Pflicht DOMPointInit Punkt im Benutzerkoordinatensystem für getCharNumAtPosition(). Zurückgegeben wird der Index des Zeichens an dieser Stelle oder -1, wenn dort kein Zeichen liegt.

Rückgabewert

Typ
SVGTextContentElement
Beschreibung
Die Instanz ist über <text>-, <tspan>- und <textPath>-Elemente verfügbar. Die Messmethoden liefern number, DOMPoint oder DOMRect.

Beispiele

Textelement erzeugen und Breite messen

const SVG_NS = 'http://www.w3.org/2000/svg';
const svg = document.createElementNS(SVG_NS, 'svg');
svg.setAttribute('width', '300');
svg.setAttribute('height', '60');

const text = document.createElementNS(SVG_NS, 'text');
text.setAttribute('x', '10');
text.setAttribute('y', '35');
text.textContent = 'Umsatz 2024';
svg.append(text);
document.body.append(svg); // Messen funktioniert erst nach dem Einhängen

console.log(text instanceof SVGTextContentElement);
console.log('Zeichen:', text.getNumberOfChars());
console.log('Breite:', text.getComputedTextLength().toFixed(1));
true Zeichen: 11 Breite: 85.3 (abhängig von der Schrift)

Beschriftung zu lang? Mit Auslassungszeichen kürzen

const truncateLabel = (textEl, maxWidth) => {
  const original = textEl.textContent;
  if (textEl.getComputedTextLength() <= maxWidth) return;
  let len = original.length;
  while (len > 0) {
    textEl.textContent = original.slice(0, len) + '…';
    if (textEl.getComputedTextLength() <= maxWidth) break;
    len--;
  }
  textEl.setAttribute('title', original);
};

const label = document.querySelector('svg text.axis-label');
truncateLabel(label, 80);
console.log(label.textContent);
Sehr lange Ach…

Hintergrundbox hinter ein Zeichen und textLength setzen

const text = document.querySelector('#headline'); // <text> im DOM

// Box um das dritte Zeichen zeichnen
const box = text.getExtentOfChar(2);
const rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
Object.entries({ x: box.x, y: box.y, width: box.width, height: box.height, fill: 'gold' })
  .forEach(([k, v]) => rect.setAttribute(k, v));
text.before(rect);

// Text auf exakt 200 Einheiten strecken, nur über den Zeichenabstand
text.textLength.baseVal.value = 200;
text.lengthAdjust.baseVal = SVGTextContentElement.LENGTHADJUST_SPACING;
console.log(text.getComputedTextLength());
200

Welches Zeichen wurde angeklickt?

const text = document.querySelector('svg text');

text.addEventListener('click', (event) => {
  const svg = text.ownerSVGElement;
  const pt = new DOMPoint(event.clientX, event.clientY)
    .matrixTransform(text.getScreenCTM().inverse());
  const index = text.getCharNumAtPosition(pt);
  if (index >= 0) {
    console.log(`Zeichen ${index}: "${text.textContent[index]}"`);
  }
});
Zeichen 4: "a"

// Wichtig · Fallstricke

  • Nicht gerendert heißt: keine Messwerte. Hängt das Element nicht im DOM oder ist es mit display: none ausgeblendet, liefert getComputedTextLength() in der Regel 0. Die zeichenbezogenen Methoden können dann eine IndexSizeError-Ausnahme werfen.
  • Webfonts: Wer vor dem Laden der Schrift misst, bekommt falsche Werte. Vorher mit await document.fonts.ready auf die Schrift warten.
  • Zeichenindizes zählen UTF-16-Codeeinheiten. Emojis und Zeichen außerhalb der BMP (Basic Multilingual Plane) belegen je nach Browser zwei Indizes. Ein ungültiger charnum wirft IndexSizeError.
  • Koordinaten: Die Ergebnisse gelten im lokalen Benutzerkoordinatensystem. Für Bildschirmkoordinaten muss man mit getScreenCTM() umrechnen.
  • Performance: Jede Messung kann ein synchrones Layout erzwingen. In Schleifen sollte man Schreib- und Lesezugriffe daher bündeln.
  • selectSubString() ist veraltet und wird nicht zuverlässig unterstützt. Stattdessen die Selection-API verwenden.
  • Browser-Kompatibilität: Die Kernmethoden werden von allen modernen Browsern unterstützt. getCharNumAtPosition() akzeptiert in neueren Browsern ein DOMPointInit, ältere erwarteten ein SVGPoint aus svg.createSVGPoint().