Signatur
Beschreibung
Die Methode getNumberOfChars() gibt es auf allen Elementen, die von SVGTextContentElement erben, also auf <text>, <tspan> und <textPath>. Sie gibt zurück, wie viele adressierbare Zeichen das Element enthält, einschließlich der Zeichen in verschachtelten <tspan>-Kindelementen.
„Adressierbar“ heißt: Gezählt werden die Zeichen, auf die man über einen Index mit Methoden wie getStartPositionOfChar(), getExtentOfChar(), getRotationOfChar() oder getSubStringLength() zugreifen kann. Die Zählung erfolgt in UTF-16-Code-Einheiten, genauso wie bei String.prototype.length. Zeichen, die zum Beispiel wegen Überlaufs nicht sichtbar sind, zählen trotzdem mit.
Die Methode wird vor allem als Obergrenze für Schleifen über die zeichenbezogenen Geometrie-Methoden genutzt, etwa um einzelne Buchstaben zu animieren, Zeichen hervorzuheben, Text mit Auslassungspunkten zu kürzen oder Treffer beim Anklicken zu bestimmen (in Kombination mit getCharNumAtPosition()).
Beispiele
Zeichen in einem Textelement zählen
// HTML: <svg><text id="titel" x="10" y="30">Hallo <tspan fill="red">SVG</tspan></text></svg>
const text = document.getElementById('titel');
console.log(text.getNumberOfChars());
console.log(text.querySelector('tspan').getNumberOfChars());
Einzelne Zeichen mit Rechtecken markieren
const svgNS = 'http://www.w3.org/2000/svg';
const text = document.querySelector('svg text');
const svg = text.ownerSVGElement;
const anzahl = text.getNumberOfChars();
for (let i = 0; i < anzahl; i++) {
const box = text.getExtentOfChar(i); // DOMRect des Zeichens
const rect = document.createElementNS(svgNS, 'rect');
rect.setAttribute('x', box.x);
rect.setAttribute('y', box.y);
rect.setAttribute('width', box.width);
rect.setAttribute('height', box.height);
rect.setAttribute('fill', 'none');
rect.setAttribute('stroke', i % 2 ? 'steelblue' : 'orange');
svg.insertBefore(rect, text);
}
Text auf maximale Breite kürzen (Auslassungspunkte)
const kuerzeText = (textEl, maxBreite) => {
const original = textEl.textContent;
if (textEl.getComputedTextLength() <= maxBreite) return;
let n = textEl.getNumberOfChars();
// so lange Zeichen entfernen, bis Text + „…“ passt
while (n > 0) {
textEl.textContent = original.slice(0, --n) + '…';
if (textEl.getComputedTextLength() <= maxBreite) break;
}
};
kuerzeText(document.querySelector('#label'), 120);
Emoji: Zählung in UTF-16-Einheiten
// <text id="emo" x="0" y="20">Hi 👋</text>
const emo = document.getElementById('emo');
console.log(emo.getNumberOfChars());
console.log([...emo.textContent].length); // Codepoints
// Wichtig · Fallstricke
- UTF-16-Zählung: Zeichen außerhalb der Basic Multilingual Plane, etwa Emoji oder manche CJK-Zeichen, zählen als 2. Bei Schleifen mit
getExtentOfChar()können deshalb Indizes auf die zweite Hälfte eines Surrogatpaars zeigen. Graphem-Cluster (z. B. 👨👩👧) belegen noch mehr Einheiten. - Leerraum: Wie Leerzeichen, Zeilenumbrüche und
xml:spacebzw.white-spaceverarbeitet werden, beeinflusst das Ergebnis. Der Wert kann darum vontextContent.lengthabweichen, und ältere Browser haben zusammengefallenen Leerraum teils unterschiedlich gezählt. - Die geometrischen Nachbar-Methoden (
getExtentOfChar()usw.) brauchen ein gerendertes Element. Beidisplay: noneoder einem Element, das nicht im Dokument hängt, liefern sie Nullwerte oder werfen Fehler.getNumberOfChars()selbst ist davon meist nicht betroffen. - Indizes ab
getNumberOfChars()lösen bei den zeichenbezogenen Methoden einenIndexSizeError(DOMException) aus. - Die Methode wird in allen modernen Browsern seit Langem unterstützt.