Start · Sprachen · JavaScript · Referenz · CanvasRenderingContext2D.transform()

CanvasRenderingContext2D.transform()

Methode

Multipliziert die aktuelle Transformationsmatrix des Canvas mit der Matrix aus den sechs Argumenten <code>a</code> bis <code>f</code>. Die Wirkung ist kumulativ.

seit JavaScript Baseline: alle Browser Kategorie: webapi

Signatur

CanvasRenderingContext2D.prototype.transform(a, b, c, d, e, f)

Beschreibung

transform() verknüpft die aktuelle Transformationsmatrix des 2D-Kontexts mit einer weiteren affinen Matrix. Die sechs Argumente beschreiben die Matrix [a c e; b d f; 0 0 1]. Ein Punkt (x, y) wird damit auf (a·x + c·y + e, b·x + d·y + f) abgebildet. So lassen sich Skalierung, Rotation, Scherung und Verschiebung in einem einzigen Aufruf zusammenfassen.

Die Wirkung ist kumulativ. Jeder Aufruf wird mit der bereits bestehenden Transformation multipliziert, genau wie bei translate(), rotate() und scale(). Diese drei Methoden sind im Grunde Sonderfälle von transform(). Soll die Matrix nicht ergänzt, sondern ersetzt werden, verwendet man setTransform().

Typische Einsatzfälle sind Scherungen (Kursiv-Effekte, isometrische Darstellung), für die es keine eigene Methode gibt. Dazu kommt das Übernehmen fertiger Matrizen, etwa aus einer Physik-Engine oder aus SVG/CSS. Die Transformation betrifft nur Zeichenbefehle, die danach ausgeführt werden. Bereits gezeichnete Pixel bleiben unverändert.

Parameter

Name Typ Default Beschreibung
$a Pflicht number Horizontale Skalierung (m11). 1 = keine Änderung.
$b Pflicht number Vertikale Scherung (m12): Neigung der y-Werte in Abhängigkeit von x.
$c Pflicht number Horizontale Scherung (m21): Neigung der x-Werte in Abhängigkeit von y.
$d Pflicht number Vertikale Skalierung (m22). 1 = keine Änderung.
$e Pflicht number Horizontale Verschiebung (dx) in Pixeln.
$f Pflicht number Vertikale Verschiebung (dy) in Pixeln.

Beispiele

Rechteck horizontal scheren (Kursiv-Effekt)

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');

ctx.save();
// c = -0.3 schert horizontal, e/f verschieben den Ursprung
ctx.transform(1, 0, -0.3, 1, 60, 20);
ctx.fillStyle = 'steelblue';
ctx.fillRect(0, 0, 120, 80);
ctx.restore(); // Transformation wieder zurücksetzen

console.log(ctx.getTransform().toString());
matrix(1, 0, 0, 1, 0, 0)

Kumulative Wirkung im Vergleich zu setTransform()

const ctx = document.createElement('canvas').getContext('2d');

ctx.transform(2, 0, 0, 2, 0, 0); // Skalierung ×2
ctx.transform(2, 0, 0, 2, 0, 0); // erneut ×2 → insgesamt ×4
console.log(ctx.getTransform().a);

ctx.setTransform(2, 0, 0, 2, 0, 0); // ersetzt → wieder ×2
console.log(ctx.getTransform().a);
4 2

Rotation um einen Mittelpunkt mit einer einzigen Matrix

const ctx = document.querySelector('canvas').getContext('2d');

const rotateAround = (ctx, angle, cx, cy) => {
  const cos = Math.cos(angle);
  const sin = Math.sin(angle);
  // entspricht translate(cx, cy) · rotate(angle) · translate(-cx, -cy)
  ctx.transform(cos, sin, -sin, cos,
    cx - cos * cx + sin * cy,
    cy - sin * cx - cos * cy);
};

ctx.save();
rotateAround(ctx, Math.PI / 6, 150, 100);
ctx.fillStyle = 'tomato';
ctx.fillRect(100, 75, 100, 50);
ctx.restore();

Isometrische Kachel zeichnen

const ctx = document.querySelector('canvas').getContext('2d');

ctx.save();
// Isometrische Projektion: 45°-Drehung plus vertikale Stauchung
ctx.transform(0.707, 0.409, -0.707, 0.409, 200, 50);
for (let x = 0; x < 4; x++) {
  for (let y = 0; y < 4; y++) {
    ctx.fillStyle = (x + y) % 2 ? '#8bc34a' : '#689f38';
    ctx.fillRect(x * 40, y * 40, 40, 40);
  }
}
ctx.restore();

// Wichtig · Fallstricke

  • Kumulativ: Wer transform() in einer Animationsschleife aufruft, ohne vorher save()/restore() oder resetTransform() zu nutzen, sammelt die Transformationen Frame für Frame an. Das führt schnell zu „davonfliegenden“ Grafiken.
  • Reihenfolge zählt: Matrixmultiplikation ist nicht kommutativ. transform(A) gefolgt von transform(B) ergibt ein anderes Ergebnis als die umgekehrte Reihenfolge.
  • Ist ein Argument Infinity oder NaN, wird der Aufruf stillschweigend ignoriert. Es gibt keinen Fehler.
  • Eine singuläre Matrix (z. B. a = d = 0 bei b = c = 0) lässt alle folgenden Zeichnungen verschwinden.
  • lineWidth, Schatten-Offsets und Muster werden mittransformiert. Bei Scherung oder ungleicher Skalierung werden Linien dadurch verzerrt.
  • Die aktuelle Matrix lässt sich mit getTransform() als DOMMatrix auslesen. Das wird von allen modernen Browsern unterstützt, im alten Internet Explorer fehlt es. transform() selbst ist überall verfügbar, auch in OffscreenCanvasRenderingContext2D.