Signatur
Beschreibung
getScreenCTM() („Current Transformation Matrix“) gibt die Matrix zurück, die alle Transformationen vom Koordinatensystem des aktuellen Elements bis zum Viewport des Dokuments zusammenfasst: eigene transform-Attribute, Transformationen aller Vorfahren, die viewBox-Skalierung samt preserveAspectRatio sowie die Position des äußeren <svg> auf der Seite (inklusive Scrollposition).
In der Praxis ist die Methode das Werkzeug, um Mausereignisse und SVG-Koordinaten zusammenzubringen. Mit der Matrix selbst rechnet man lokale SVG-Koordinaten in Client-Koordinaten um (z. B. um ein HTML-Tooltip neben einem SVG-Element zu platzieren). Mit ihrer Inversen (.inverse()) rechnet man event.clientX/clientY in das Koordinatensystem eines Elements zurück, was für Drag & Drop, Zeichen-Tools oder Klick-Positionen in Diagrammen nötig ist.
Im Unterschied dazu liefert getCTM() nur die Matrix bis zum nächsten Viewport-Element (nearestViewportElement), ohne die Position des SVGs im HTML-Dokument. Die Matrix hat die Form [a b c d e f]; a/d enthalten Skalierung, e/f die Verschiebung.
Rückgabewert
DOMMatrix, historisch SVGMatrix) mit den Werten a–f. null, wenn die Matrix nicht bestimmt werden kann, etwa wenn das Element nicht gerendert wird (z. B. display: none oder nicht im Dokument eingehängt).Beispiele
Mausposition in SVG-Koordinaten umrechnen
const svg = document.querySelector('svg');
const toSvgPoint = (evt, element = svg) => {
const ctm = element.getScreenCTM();
if (!ctm) return null; // Element nicht gerendert
const pt = new DOMPoint(evt.clientX, evt.clientY);
return pt.matrixTransform(ctm.inverse());
};
svg.addEventListener('click', (evt) => {
const p = toSvgPoint(evt);
console.log(`SVG-Koordinaten: ${p.x.toFixed(1)}, ${p.y.toFixed(1)}`);
});
Drag & Drop eines Kreises innerhalb einer viewBox
const svg = document.querySelector('svg');
const circle = svg.querySelector('circle');
let offset = null;
const svgPoint = (evt) =>
new DOMPoint(evt.clientX, evt.clientY)
.matrixTransform(svg.getScreenCTM().inverse());
circle.addEventListener('pointerdown', (evt) => {
const p = svgPoint(evt);
offset = { x: p.x - circle.cx.baseVal.value, y: p.y - circle.cy.baseVal.value };
circle.setPointerCapture(evt.pointerId);
});
circle.addEventListener('pointermove', (evt) => {
if (!offset) return;
const p = svgPoint(evt);
circle.setAttribute('cx', p.x - offset.x);
circle.setAttribute('cy', p.y - offset.y);
});
circle.addEventListener('pointerup', () => { offset = null; });
HTML-Tooltip an einem transformierten SVG-Element platzieren
const rect = document.querySelector('#balken');
const tooltip = document.querySelector('#tooltip'); // position: fixed
const showTooltip = () => {
const box = rect.getBBox(); // lokale Koordinaten
const ctm = rect.getScreenCTM();
// obere rechte Ecke in Client-Koordinaten
const corner = new DOMPoint(box.x + box.width, box.y).matrixTransform(ctm);
tooltip.style.left = `${corner.x + 8}px`;
tooltip.style.top = `${corner.y}px`;
tooltip.hidden = false;
console.log(ctm.a, ctm.e, ctm.f);
};
rect.addEventListener('mouseenter', showTooltip);
// Wichtig · Fallstricke
- Nicht cachen: Die Matrix ändert sich bei Scrollen, Größenänderung des Fensters, Layout-Änderungen und geänderten
transform-Attributen. Rufe sie deshalb im Event-Handler jeweils neu ab. nullprüfen: Bei nicht gerenderten Elementen (display: none, nicht im DOM, teils innerhalb von<defs>) gibt die Methodenullzurück; ein direkter Aufruf von.inverse()würde dann einenTypeErrorauslösen.- Bezugssystem: Trotz des Namens beziehen sich die Werte auf den Viewport (Client-Koordinaten wie
clientX), nicht auf den physischen Bildschirm (screenX). - CSS-Transformationen: CSS-
transformauf Vorfahren (auch HTML-Elemente) wird in aktuellen Browsern berücksichtigt, 3D-Transformationen lassen sich aber nicht in einer 2D-Matrix abbilden; ältere Browser zeigten hier Abweichungen. - Ältere Browser: Wenn
DOMPointfehlt, funktioniert der klassische Wegsvg.createSVGPoint()+point.matrixTransform(matrix).SVGMatrixist in modernen Browsern ein Alias fürDOMMatrix.