Start · Sprachen · JavaScript · Referenz · SVGGeometryElement.isPointInStroke()

SVGGeometryElement.isPointInStroke()

Methode

Prüft, ob ein Punkt im lokalen Koordinatensystem des Elements innerhalb der Umrissform (Stroke) eines SVG-Geometrie-Elements liegt.

seit JavaScript Baseline: alle modernen Browser (Chrome 48+, Firef Kategorie: webapi

Signatur

SVGGeometryElement.prototype.isPointInStroke(point)

Beschreibung

isPointInStroke() ist auf allen SVG-Geometrie-Elementen verfügbar, also z. B. <path>, <circle>, <rect>, <line>, <polyline> und <polygon>. Die Methode gibt true zurück, wenn der übergebene Punkt auf dem gezeichneten Umriss liegt. Dabei berücksichtigt der Browser die Umriss-Eigenschaften wie stroke-width, stroke-linecap, stroke-linejoin und stroke-miterlimit.

Typische Einsatzfälle sind eine präzise Trefferprüfung für dünne Linien und Pfade (z. B. in Diagramm-Editoren, Zeichenwerkzeugen oder Karten), eine eigene Kollisionserkennung oder die Frage, ob ein Klick eine Kante und nicht die Fläche getroffen hat. Für die Füllfläche gibt es die Schwestermethode isPointInFill().

Wichtig: Der Punkt wird im lokalen Benutzerkoordinatensystem des Elements angegeben, nicht in Bildschirm- oder Seitenkoordinaten. Mauskoordinaten wie clientX/clientY musst du deshalb vorher mit der inversen Matrix aus getScreenCTM() umrechnen. Eigenschaften wie pointer-events, visibility oder display haben auf das Ergebnis keinen Einfluss – es wird rein geometrisch gerechnet.

Parameter

Name Typ Default Beschreibung
$point Pflicht DOMPointInit | DOMPoint | SVGPoint Der zu prüfende Punkt mit x- und y-Koordinate im lokalen Koordinatensystem des Elements. Ein einfaches Objekt wie { x: 10, y: 20 } genügt in modernen Browsern; fehlende Werte gelten als 0.

Rückgabewert

Typ
boolean
Beschreibung
true, wenn der Punkt innerhalb der Umrissform liegt, sonst false.

Beispiele

Einfache Prüfung an einem Kreis

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

const circle = document.createElementNS(svgNS, 'circle');
circle.setAttribute('cx', '100');
circle.setAttribute('cy', '100');
circle.setAttribute('r', '50');
circle.setAttribute('fill', 'none');
circle.setAttribute('stroke', 'black');
circle.setAttribute('stroke-width', '10');

svg.append(circle);
document.body.append(svg);

// Umriss reicht von Radius 45 bis 55
console.log(circle.isPointInStroke({ x: 100, y: 100 })); // Mittelpunkt
console.log(circle.isPointInStroke({ x: 150, y: 100 })); // genau auf der Linie
console.log(circle.isPointInStroke({ x: 154, y: 100 })); // noch im 10px-Umriss
console.log(circle.isPointInStroke({ x: 160, y: 100 })); // außerhalb
false true true false

Mausposition auf einem Pfad erkennen (mit Koordinatenumrechnung)

// HTML: <svg id="chart" viewBox="0 0 400 200"><path id="kurve" d="M10 150 Q 200 0 390 150" fill="none" stroke="steelblue" stroke-width="8"/></svg>
const svg = document.querySelector('#chart');
const path = document.querySelector('#kurve');

const toLocal = (element, clientX, clientY) => {
  const matrix = element.getScreenCTM()?.inverse();
  if (!matrix) return null;
  return new DOMPoint(clientX, clientY).matrixTransform(matrix);
};

svg.addEventListener('pointermove', (event) => {
  const point = toLocal(path, event.clientX, event.clientY);
  const hit = point !== null && path.isPointInStroke(point);
  path.setAttribute('stroke', hit ? 'tomato' : 'steelblue');
  svg.style.cursor = hit ? 'pointer' : 'default';
});

Kanten- oder Flächentreffer unterscheiden

const rect = document.querySelector('rect'); // z. B. fill="#eee" stroke="#333" stroke-width="6"

const classifyHit = (element, point) => {
  if (element.isPointInStroke(point)) return 'Kante';
  if (element.isPointInFill(point)) return 'Fläche';
  return 'daneben';
};

rect.ownerSVGElement.addEventListener('click', (event) => {
  const matrix = rect.getScreenCTM().inverse();
  const point = new DOMPoint(event.clientX, event.clientY).matrixTransform(matrix);
  console.log(`Treffer: ${classifyHit(rect, point)}`);
});
Treffer: Kante

Kompatibler Aufruf für ältere Browser mit SVGPoint

const isOnStroke = (element, x, y) => {
  try {
    // Moderne Browser: einfaches Objekt reicht
    return element.isPointInStroke({ x, y });
  } catch {
    // Ältere Engines verlangen ein echtes SVGPoint
    const pt = element.ownerSVGElement.createSVGPoint();
    pt.x = x;
    pt.y = y;
    return element.isPointInStroke(pt);
  }
};

const line = document.querySelector('line');
console.log(isOnStroke(line, 50, 50));
true

// Wichtig · Fallstricke

  • Koordinatensystem: Der Punkt muss in lokalen Benutzerkoordinaten des Elements angegeben werden. Wer direkt clientX/clientY übergibt, bekommt bei viewBox, Skalierung, transform oder Scrollen falsche Ergebnisse. Rechne deshalb mit getScreenCTM().inverse() und DOMPoint.matrixTransform() um.
  • Kein Umriss nötig: Die Methode wertet die berechneten Umriss-Eigenschaften aus. Bei stroke-width: 0 ist das Ergebnis immer false. Ob stroke gesetzt ist (none) oder visibility/pointer-events gesetzt sind, spielt dagegen keine Rolle.
  • Gestrichelte Linien: Wie stroke-dasharray behandelt wird, war lange uneinheitlich zwischen den Browsern. Verlasse dich bei gestrichelten Linien nicht auf pixelgenaue Treffer in den Lücken.
  • Nicht gerenderte Elemente: Elemente mit display: none oder außerhalb des Dokuments können je nach Browser false liefern, weil keine Layoutdaten vorhanden sind.
  • Kompatibilität: Ältere Firefox- (vor Version 69) und Safari-Versionen verlangen ein SVGPoint aus createSVGPoint() statt eines einfachen Objekts. Moderne Browser akzeptieren DOMPointInit. Der Internet Explorer unterstützt die Methode nicht.
  • Leistung: Bei sehr vielen Elementen und häufigen pointermove-Ereignissen kann die Prüfung teuer werden. Grenze die Kandidaten vorher über getBBox() ein oder drossle die Abfrage mit requestAnimationFrame.