Start · Sprachen · JavaScript · Referenz · SVGTextContentElement.getCharNumAtPosition()

SVGTextContentElement.getCharNumAtPosition()

Methode

Gibt den Index des Zeichens zurück, dessen gerendertes Glyph an einem bestimmten Punkt im Benutzerkoordinatensystem liegt, oder <code>-1</code>, wenn dort kein Zeichen ist.

seit JavaScript Baseline: alle modernen Browser (SVG 1.1, in SVG 2 Kategorie: webapi

Signatur

SVGTextContentElement.prototype.getCharNumAtPosition(point)

Beschreibung

getCharNumAtPosition() führt einen Treffertest auf Zeichenebene für SVG-Textelemente wie <text>, <tspan> und <textPath> durch. Du übergibst einen Punkt und erhältst den Index des Zeichens zurück, dessen Glyph-Zelle diesen Punkt enthält. Liegt an der Stelle kein Glyph, ist der Rückgabewert -1.

Typische Einsatzfälle sind interaktive SVG-Grafiken: das Zeichen unter dem Mauszeiger hervorheben, eine eigene Textauswahl oder einen Cursor in SVG-Texteditoren umsetzen, Tooltips für einzelne Buchstaben anzeigen oder auf einen Klick auf ein bestimmtes Wort in einem gebogenen Text (<textPath>) reagieren.

Wichtig: Der Punkt wird im Benutzerkoordinatensystem des Elements erwartet, nicht in Bildschirm- oder Viewport-Koordinaten. Mauskoordinaten aus clientX/clientY musst du daher erst mit getScreenCTM().inverse() umrechnen. Der zurückgegebene Index bezieht sich auf die Zeichen des Elements (UTF-16-Codeeinheiten) und lässt sich direkt mit Methoden wie getExtentOfChar() oder getStartPositionOfChar() weiterverwenden.

Parameter

Name Typ Default Beschreibung
$point Pflicht DOMPoint | DOMPointInit | SVGPoint Der zu prüfende Punkt mit den Eigenschaften x und y im Benutzerkoordinatensystem des Textelements. Laut SVG 2 genügt ein DOMPointInit-Objekt; für maximale Kompatibilität eignet sich svg.createSVGPoint() oder new DOMPoint(x, y).

Rückgabewert

Typ
number
Beschreibung
Ganzzahliger Index (long) des Zeichens an der angegebenen Position; -1, wenn an dieser Stelle kein Zeichen gerendert ist.

Beispiele

Einfacher Treffertest an einer festen Koordinate

// <svg id="bild" width="300" height="100"><text id="titel" x="10" y="50" font-size="32">Hallo SVG</text></svg>
const text = document.getElementById('titel');

const index = text.getCharNumAtPosition(new DOMPoint(20, 45));
console.log(index, text.textContent[index]);

// Punkt außerhalb des Textes
console.log(text.getCharNumAtPosition(new DOMPoint(290, 90)));
0 H -1

Zeichen unter dem Mauszeiger ermitteln

const svg = document.getElementById('bild');
const text = document.getElementById('titel');

const toUserSpace = (evt, element) => {
  // Bildschirmkoordinaten in Benutzerkoordinaten umrechnen
  const pt = new DOMPoint(evt.clientX, evt.clientY);
  return pt.matrixTransform(element.getScreenCTM().inverse());
};

svg.addEventListener('mousemove', (evt) => {
  const point = toUserSpace(evt, text);
  const index = text.getCharNumAtPosition(point);
  if (index !== -1) {
    console.log(`Zeichen ${index}: "${text.textContent[index]}"`);
  }
});
Zeichen 4: "o"

Angeklicktes Zeichen mit einem Rechteck hervorheben

const SVG_NS = 'http://www.w3.org/2000/svg';
const svg = document.getElementById('bild');
const text = document.getElementById('titel');

const marker = document.createElementNS(SVG_NS, 'rect');
marker.setAttribute('fill', 'rgba(255, 200, 0, 0.5)');
svg.insertBefore(marker, text);

text.addEventListener('click', (evt) => {
  const point = new DOMPoint(evt.clientX, evt.clientY)
    .matrixTransform(text.getScreenCTM().inverse());
  const index = text.getCharNumAtPosition(point);
  if (index === -1) return;

  const { x, y, width, height } = text.getExtentOfChar(index);
  Object.entries({ x, y, width, height })
    .forEach(([key, value]) => marker.setAttribute(key, value));
});

// Wichtig · Fallstricke

  • Koordinatensystem: Häufigster Fehler ist die direkte Übergabe von clientX/clientY. Ohne Umrechnung über getScreenCTM().inverse() passen die Ergebnisse nur zufällig – spätestens bei viewBox, Skalierung, Scrollen oder transform gibt es falsche Treffer oder -1.
  • Zeichenindex ≠ sichtbares Zeichen: Der Index zählt UTF-16-Codeeinheiten. Emojis oder andere Zeichen außerhalb der BMP belegen zwei Indizes; Ligaturen können mehrere Zeichen auf ein Glyph abbilden.
  • Bei überlappenden Glyphen (z. B. durch dx/rotate) liefert die Methode laut Spezifikation das Zeichen, das zuletzt gerendert wurde, also optisch oben liegt.
  • Das Element muss gerendert sein. Bei display: none oder vor dem Einfügen ins DOM ist kein sinnvolles Ergebnis zu erwarten.
  • Kompatibilität: Wird von allen modernen Browsern unterstützt. Ältere Browser erwarten teils zwingend ein SVGPoint (über svg.createSVGPoint()) statt eines einfachen Objekts oder DOMPoint.