Canvas Transformationen: rotate

Rotation: Canvas Formen rotieren um einen Mittelpunkt

Das Rotieren einer Zeichnung im Canvas läuft anders ab als in Grafikprogrammen, in CSS oder Inkscape, denn rotate () rotiert nicht die Form, sondern das Koordinatensystem des Canvas um dem Nullpunkt oben links.

23-02-02 SITEMAP CSS HTML JS Basis JS Web Tutorial SVG

Canvas vs CSS-Transformationen und Inkscape/Illustrator

Die Zeichnungen im Canvas sind keine Objekte, sondern bestehen aus einer Schicht von Pixeln, die sofort mit dem Canvas verschmelzen – ein digitales Ölbild. Transformationen wie rotate, scale und transform müssen vor dem Zeichnen einer Form angewendet werden, erst dann wird die Form auf dem Canvas aufgetragen.

In Grafikprogrammen wie Adobe Illustrator oder Inkscape drehen wir Elemente um ihren Mittelpunkt. Eine Form in einem Canvas hingegen wird nicht um ihren Mittelpunkt gedreht, sondern um den Nullpunkt des Canvas oben links. In der Animation verschwindet die Form, bis sie wieder im sichtbaren Viewport des Canvas erscheint.

ctx.rotate(radianAngle);
ctx.beginPath();
ctx.fillStyle = "red";
ctx.rect(60,60,30,50);
ctx.fill();

Wer von CSS-Transformationen und Grafikprogrammen kommt, muss beim HTML-Canvas neue Verhalten lernen:

  • Nicht die Zeichnung, sondern der Context wird rotiert – vorübergehend.
  • Die Zeichnung ist kein Objekt, sondern der Canvas besteht aus nur einer Schicht von Pixeln.
  • Rotiert wird nicht mit Grad-Angaben, sondern in Radiant.

Canvas-Rotation um den Nullpunkt: rotate ()

Eine Transformation bewegt keine Elemente wie Transformationen in Inkscape, Illustrator oder CSS-Transformationen, sondern die Transformation ändert das Koordinatensystem.

Ohne weitere Angaben rotiert ctx.rotate() die Form um den Nullpunkt des Canvas oben links.

Der Effekt der Rotation ist nur im Canvas sichtbar. Das Canvas ist sozusagen ein Fenster zum vierten Quadranten eines Kreises. Die Diagonale des Canvas ist der Durchmesser dieses Kreises.

Quadrant IQuadrant IIQuadrant IIIQuadrant IVCANVAS
Canvas ist immer der vierte Quadrant eines Kreis um den Nullpunkt. Nicht die Form auf dem Canvas wird gedreht – der Canvas ist nur die sichtbare Fläche für Pixel. Sobald die Pixel auf den Canvas gesetzt wurden, sind sie Teil des Canvas und kein selbstständiges Element wie eine Ebene in Photoshop oder ein Objekt in SVG.

Context translate () / Context rotate ()

Damit eine Form im Canvas um einen selbstbestimmten Punkt rotiert, wird der Nullpunkt des Koordinatensystems mit translate (newX,newY) verschoben. Im Beispiel des roten Rechtecks oben auf den Mittelpunkt des Rechtecks.

…
const ctx = canvas.getContext("2d");
ctx.rect(60, 40, 30, 50);
ctx.fillStyle = "green";
ctx.fill();
…
const ctx = canvas.getContext("2d");
ctx.translate(60,40); // versetzt den Nullpunkt
ctx.rect(0, 0, 30, 50);
ctx.fillStyle = "red";
ctx.fill();

Vor der Transformation und Rotation speichert ctx.save() den Zustand des Context. Am Ende stellt ctx.restore () der Original-Kontext vor der Transformation und Rotation wieder her.

ctx.save();
ctx.translate(75,65);
ctx.rotate(radianAngle);
ctx.beginPath();
ctx.fillStyle = "red";
ctx.rect(-15,-25,30,50);
ctx.fill();
ctx.restore();

Context löschen: clearRect

In einer Zeichnung mit SVG oder bei DOM-Elementen in einem HTML-Dokument bleibt ein Element bei Transformationen wie Rotation oder Skalieren erhalten und kann zu jeder Zeit weiter oder erneut transformiert werden.

Aktionen auf dem Canvas hingegen erzeugen keine Elemente, sondern Pixel. Die Form auf dem Canvas ist kein eigenständiges Element wie ein Rechteck im Illustrationsprogramm oder in SVG, sondern die Form verschmilzt sofort nach der fill-Anweisung mit dem Canvas und wird als Form vergessen.

Wenn der Canvas vor dem Aufruf von ctx.rotate() nicht gelöscht wird, bleibt die Zeichnung stehen und wird durch die Rotation überlagert. Obendrein akkumulieren Transformationen – jeder Rotation geht von der letzten Transformation aus.

Der Context wird mit clearRect () vor jedem Frame der Animation gelöscht und neu mit den veränderten Koordinaten gezeichnet.

Context löschen und das orange Rechteck wieder an derselben Stelle zeichnen

ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.beginPath(); 
ctx.fillStyle = "orange";
ctx.rect(30,30,30,50);
ctx.fill(); 
ctx.save();

Context versetzen mit translate, rotieren mit rotate und das rote Rechteck zeichnen

ctx.translate(150,100); // Nullpunkt auf den Mittelpunkt des Canvas setzen
ctx.rotate(radianAngle);
ctx.beginPath();
ctx.fillStyle = "red";
ctx.lineStyle = "#000";
ctx.rect(30,30,30,50);
ctx.fill();
ctx.stroke();

Am Ende des Frames den Context wieder zurücksetzen

ctx.restore();

Canvas Rotation und Animation

Der Kontext des Canvas rotiert nicht mit der üblichen Angabe in 0 bis 360°, sondern die Rotation wird in Radiant angegeben (siehe auch Javascript Zeichnen und Animieren mit dem HTML Canvas-Element).

2πrad = 360°

oder

1rad= 360° 2 π =180° π57,29578
let canvas = document.getElementById("canvas-animate");
let ctx = canvas.getContext("2d");

let p1 = {x:60,y:40}; // Ecke oben links
let p2 = {x:90,y:70}; // Ecke unten rechts
let dx = p2.x-p1.x;
let dy = p2.y-p1.y;
let length = Math.sqrt(dx*dx+dy*dy);
let angle = Math.atan2(dy,dx);

draw(angle);
requestAnimationFrame(animate);

function animate(time){        // Animieren mit requestAnimationFrame
  requestAnimationFrame(animate);
  draw(angle);
  angle += Math.PI/60;
}

function draw(radianAngle){
   // Bei jedem Frame den Context vollständig löschen
   ctx.clearRect(0,0,canvas.width,canvas.height);
   ctx.beginPath();
   ctx.fillStyle = "orange";  // Orange bleibt stehen
   ctx.rect(p1.x,p1.y,30,50);
   ctx.fill();
   ctx.save();                // Context speichern
   
   // Nullpunkt auf die Mitte des Canvas
   ctx.translate(canvas.width/2,canvas.height/2);    
   ctx.rotate(radianAngle);
   ctx.beginPath();
   ctx.fillStyle = "red";
   ctx.rect(-15,-25,30,50);
   ctx.fill();
   ctx.restore();             // Content wiederherstellen
}

Aber im Grunde genommen reicht es nicht, nur den sichtbaren Bereich des Canvas zu löschen – die Pixel, die bei der Rotation des Bildes entstanden sind, liegen auch innerhalb des sichtbaren Quadranten IV.