Signatur
Beschreibung
isPointInPath() prüft, ob ein Punkt in der Füllfläche eines Pfads liegt. Ohne path-Argument wird der aktuelle Pfad des Kontexts geprüft, also der, der mit beginPath(), moveTo(), arc(), rect() usw. aufgebaut wurde. Alternativ kann man ein Path2D-Objekt übergeben. Das ist in der Praxis meist die bessere Wahl, weil sich damit mehrere Formen unabhängig voneinander speichern und prüfen lassen.
Typisch ist der Einsatz beim Hit-Testing: Man findet heraus, ob ein Mausklick oder eine Berührung eine gezeichnete Form getroffen hat, etwa in Diagrammen, Spielen, Editoren oder Karten. Weil das Canvas nur Pixel speichert und keine Objekte, ist das der Standardweg, um interaktive Formen umzusetzen.
Die Koordinaten x und y gelten im Koordinatensystem des Canvas-Bitmaps und werden von der aktuellen Transformation nicht beeinflusst. Der Pfad dagegen wird mit der Transformation ausgewertet, die beim Aufbau galt (beim aktuellen Pfad) bzw. die jetzt gilt (bei Path2D). Mausposition aus einem Event muss man deshalb in Canvas-Pixel umrechnen. Das gilt besonders, wenn das Canvas per CSS skaliert ist oder für hochauflösende Bildschirme (devicePixelRatio) hochgerechnet wurde.
Mit dem Parameter fillRule legt man fest, welche Regel entscheidet, was „innen“ ist: "nonzero" (Standard) oder "evenodd". Das ist wichtig bei Pfaden, die sich selbst schneiden oder Löcher haben, etwa ein Ring aus zwei Kreisen.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $path | Path2D | aktueller Pfad | Optionales Path2D-Objekt, das geprüft werden soll. Fehlt es, wird der aktuelle Pfad des Kontexts verwendet. |
| $x Pflicht | number | X-Koordinate des zu prüfenden Punkts in Canvas-Pixeln (unabhängig von der aktuellen Transformation). | |
| $y Pflicht | number | Y-Koordinate des zu prüfenden Punkts in Canvas-Pixeln. | |
| $fillRule | "nonzero" | "evenodd" | "nonzero" | Füllregel, die festlegt, ob der Punkt innerhalb des Pfads liegt: "nonzero" (Winding-Regel ungleich null) oder "evenodd" (Gerade-Ungerade-Regel). |
Rückgabewert
true, wenn der Punkt in der Füllfläche des Pfads liegt, sonst false. Punkte direkt auf dem Rand gelten nach Spezifikation als innen.Beispiele
Einfacher Test am aktuellen Pfad
const canvas = document.createElement('canvas');
canvas.width = 200;
canvas.height = 200;
const ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.rect(50, 50, 100, 60);
console.log(ctx.isPointInPath(80, 70)); // innerhalb
console.log(ctx.isPointInPath(10, 10)); // außerhalb
Klick-Erkennung mit Path2D und CSS-skaliertem Canvas
const canvas = document.querySelector('#chart');
const ctx = canvas.getContext('2d');
const shapes = [
{ name: 'Kreis', color: 'tomato', path: new Path2D() },
{ name: 'Quadrat', color: 'steelblue', path: new Path2D() }
];
shapes[0].path.arc(80, 80, 50, 0, Math.PI * 2);
shapes[1].path.rect(160, 40, 90, 90);
const draw = (hovered) => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (const s of shapes) {
ctx.fillStyle = s === hovered ? 'gold' : s.color;
ctx.fill(s.path);
}
};
// Mausposition in Canvas-Pixel umrechnen (berücksichtigt CSS-Skalierung)
const toCanvasCoords = (event) => {
const rect = canvas.getBoundingClientRect();
return {
x: (event.clientX - rect.left) * (canvas.width / rect.width),
y: (event.clientY - rect.top) * (canvas.height / rect.height)
};
};
canvas.addEventListener('pointermove', (event) => {
const { x, y } = toCanvasCoords(event);
const hit = shapes.findLast((s) => ctx.isPointInPath(s.path, x, y));
canvas.style.cursor = hit ? 'pointer' : 'default';
draw(hit);
});
canvas.addEventListener('click', (event) => {
const { x, y } = toCanvasCoords(event);
const hit = shapes.findLast((s) => ctx.isPointInPath(s.path, x, y));
if (hit) console.log(`Angeklickt: ${hit.name}`);
});
draw();
Ring mit Loch: nonzero vs. evenodd
const ctx = document.createElement('canvas').getContext('2d');
const ring = new Path2D();
ring.arc(100, 100, 80, 0, Math.PI * 2);
ring.arc(100, 100, 40, 0, Math.PI * 2); // innerer Kreis, gleiche Drehrichtung
// Punkt im Loch (Mittelpunkt)
console.log(ctx.isPointInPath(ring, 100, 100)); // nonzero
console.log(ctx.isPointInPath(ring, 100, 100, 'evenodd')); // evenodd
// Punkt im Ring selbst
console.log(ctx.isPointInPath(ring, 100, 35, 'evenodd'));
// Wichtig · Fallstricke
- Koordinaten umrechnen:
event.offsetX/clientXsind CSS-Pixel. Ist das Canvas per CSS skaliert oder mitdevicePixelRatiohochgerechnet, muss man mitcanvas.width / rect.widthmultiplizieren, sonst liegen die Treffer daneben. - Transformationen: Der Testpunkt wird nicht transformiert. Bei
Path2Dwird die aktuelle Transformation auf den Pfad angewendet. Wurde die Form mittranslate()/scale()gezeichnet, muss beim Test dieselbe Transformation aktiv sein (z. B. zwischensave()undrestore()). - Nur Füllfläche: Die Methode ignoriert die Linienstärke. Für Treffer auf Linien und Konturen nimmt man
isPointInStroke(). - Aktueller Pfad ist flüchtig: Ohne
Path2Dwird der zuletzt aufgebaute Pfad geprüft. Nach dem nächstenbeginPath()ist er weg. Für mehrere Formen sollte man deshalbPath2Dverwenden. - Nicht endliche Werte (
NaN,Infinity) fürx/yergebenfalse. - Kompatibilität: Die Grundform funktioniert in allen Browsern. Die Überladung mit
Path2DundfillRulegeht in allen modernen Browsern, aber nicht im Internet Explorer. AuchOffscreenCanvasRenderingContext2Dbietet die Methode an. - Leistung: Bei sehr vielen Formen jede einzeln zu prüfen, kann langsam werden. Dann hilft eine Vorauswahl über Begrenzungsrechtecke (Bounding Boxes).