Start · Sprachen · JavaScript · Referenz · SVGGraphicsElement.getScreenCTM()

SVGGraphicsElement.getScreenCTM()

Methode

Liefert die Transformationsmatrix, die Koordinaten im lokalen Koordinatensystem eines SVG-Elements in Bildschirm- bzw. Client-Koordinaten (wie <code>clientX</code>/<code>clientY</code>) umrechnet.

seit JavaScript Baseline: alle Browser (SVG 1.1) Kategorie: webapi

Signatur

SVGGraphicsElement.prototype.getScreenCTM()

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

Typ
DOMMatrix | SVGMatrix | null
Beschreibung
Eine Matrix (in modernen Browsern ein 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)}`);
});
SVG-Koordinaten: 120.0, 45.5

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);
2 340 180

// 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.
  • null prüfen: Bei nicht gerenderten Elementen (display: none, nicht im DOM, teils innerhalb von <defs>) gibt die Methode null zurück; ein direkter Aufruf von .inverse() würde dann einen TypeError auslö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-transform auf 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 DOMPoint fehlt, funktioniert der klassische Weg svg.createSVGPoint() + point.matrixTransform(matrix). SVGMatrix ist in modernen Browsern ein Alias für DOMMatrix.