Einleitung zu Pfaden

Wenn wir im Canvas einen Pfad erstellen wollen, benötigen wir die Funktion beginPath(). Diese nimmt keine Parameter an und teilt unserem Canvas mit, dass alle folgenden Pfad-Methoden, wie beispielsweise lineTo(), quadraticCurveTo() oder bezierCurveTo(), in eine Liste mit Unterpfaden eingetragen werden.

Haben wir unsere Liste komplett und alle Anweisungen für unseren Pfad gebündelt, können wir nun eine der Render-Methoden, wie beispielsweise fillRect oder stroke(), aufrufen und unser Pfad wird mit allen Unterpfaden erstellt.

  • Html
  • Javascript
  • Ergebnis
<html> <head></head> <body> <canvas id="canvas_id" width="600" height="200" style="border: 1px solid red;"></canvas> </body> </html>
var Canvas = document.getElementById( "canvas_id" ); var Context = Canvas.getContext( "2d" ); Context.beginPath(); Context.lineWidth = "10"; Context.strokeStyle = "red"; Context.lineTo(200, 160); Context.bezierCurveTo(230, -40, 300, 200, 400, 150); Context.lineTo(500, 90); Context.stroke();

Das obige Beispiel zeigt einen Pfad bestehend aus zwei Linien und einer Bezier-Kurve. Mit der Funktion stroke() haben wir unserem Canvas mitgeteilt, alle Unterpfade zu einem Pfad zu rendern.

Pfad Methoden

Wenn wir Unterpfade erstellen wollen, nachdem wir die Funktion beginPath() aufgerufen haben, können wir uns allerhand an Methoden bedienen. Im Folgenden werden diese kurz erläutert und anschließend eingehend besprochen. Die Funktionen lineTo() und moveTo() wurden bereits in einem anderen Tutorial besprochen.

MethodeBeschreibung
moveTo()Bewegt den Cursor an eine gewünschte Stelle.
lineTo()Zeichnet eine Linie zur angegebenen Koordinate
rect()Zeichnet ein Rechteck.
arc()Zeichnet eine Kurve.
arcTo()Zeichnet eine Kurve unter Einbezug des vorangegangenen Unterpfades.
closePath()Verbindet das Ende mit dem Startpunkt des Pfades.
isPointInPath()Prüft, ob sich die Koordinate in einem Pfad befindet.
quadrativCurveTo()Zeichnet eine quadratische Kurve.
bezierCurveTo()Zeichnet eine Bezierkurve

Ein Rechteck zeichnen

Methoden für Rechtecke sind uns schon aus den vorangegangenen Artikeln bekannt: fillRect() , strokeRect() und clearRect(). Der Unterschied dieser Methoden zu rect() liegt darin, dass sie sofort eine Ausgabe im Canvas erzeugen.

Mit der Pfad-Methode rect( x, y, w, h ) erzeugen wir allerdings einen Unterpfad und können anschließend weitere Unterpfade hinzufügen. Sie nimmt folgende Parameter an:

ParameterBeschreibung
xGibt die X-Koordinate der oberen linken Ecke des Rechtecks an.
yGibt die Y-Koordinate der oberen linken Ecke des Rechtecks an.
wGibt die Breite an.
hGibt die Höhe an.
  • Html
  • Javascript
  • Ergebnis
<html> <head></head> <body> <canvas id="canvas_id" width="600" height="200" style="border: 1px solid red;"></canvas> </body> </html>
var Canvas = document.getElementById( "canvas_id" ); var Context = Canvas.getContext( "2d" ); Context.beginPath(); Context.strokeStyle = "red"; Context.rect( 200, 50, 200, 100 ); Context.lineTo( 300, 150 ); Context.lineTo( 400, 50 ); Context.stroke();

Im obigen Beispiel haben wir ein Rechteck von der oberen linken Ecke 200/50 mit einer Breite von 200px und Höhe von 100px erzeugt und anschließend einen Strich zur unteren Mitte und oberen rechten Ecke des Rechtecks gezogen.

Wichtig ist dabei: Der Cursor zum Weiterzeichnen liegt am Startpunkt des Rechtecks. Von diesem Punkt aus wird weiter gezeichnet.

Eine Kurve zeichnen

Das Wort "arc" kommt aus dem englischen und bedeutet "Kurve". Mit den gleichnamigen Methoden arc() und arcTo() können wir komplexe Kurven zeichnen.

Die Methode arc( x, y, radius, startWinkel, endWinkel, entgegen ) nimmt folgende Parameter an:

ParameterBeschreibung
xGibt die X-Koordinate der Kurvenmitte an.
yGibt die Y-Koordinate der Kurvenmitte an.
radiusGibt den Radius der Kurve an.
startWinkelStartwinkel in Radiant gemessen.
endWinkelEndwinkel in Radiant gemessen.
entgegenGibt die Richtung an.

false : Mit dem Uhrzeigersinn

true : Gegen den Uhrzeigersinn.
  • Html
  • Javascript
  • Ergebnis
<html> <head></head> <body> <canvas id="canvas_id" width="600" height="200" style="border: 1px solid red;"></canvas> </body> </html>
var Canvas = document.getElementById( "canvas_id" ); var Context = Canvas.getContext( "2d" ); Context.beginPath(); Context.strokeStyle = "red"; Context.arc( Canvas.width>>1, Canvas.height>>1, 50, Math.PI, Math.PI*2, false ); Context.stroke();

Im obigen Beispiel haben wir einen Halbkreis gezeichnet. Der Startpunkt dafür liegt in der Mitte des Canvas. Da der Startpunkt auch gleichzeitig in der Mitte des Halbkreises liegt haben wir von diesem Punkt aus einen Radius von 50px. Als Startwinkel haben wir π angegeben. Das Winkelmaß wird in der Computergrafik generell in Radianten angegeben. Die Umrechnung zur uns besser bekannten Einheit Grad ist folgende: α(radians) = α(degrees) × π / 180.

Wollen wir also einen Winkel von 360 Grad in Radiant bekommen wir als Ergebnis 6,28319 was genauer 2 π bedeutet. Das folgende Schaubild zeigt, wie die Zahl π mit dem Kreismaß zusammenhängt.

Die Zahl PI im Kreisbogen - CodingLab

Nun ist klar, warum wir einen unteren Halbkreis bekommen, denn der Startwinkel liegt bei π, welches auf der horizontalen X-Achse liegt. Der Endwinkel liegt bei π × 2, sodass wir eine Kurve im Abstand 50px von π bis π × 2 bekommen.

Da wir den Start- und Endpunkt gesetzt haben, können wir nun den Kreis auch in gegen gesetzte Richtung zeichnen, indem wir den letzten Parameter auf true setzen.

  • Html
  • Javascript
  • Ergebnis
<html> <head></head> <body> <canvas id="canvas_id" width="600" height="200" style="border: 1px solid red;"></canvas> </body> </html>
var Canvas = document.getElementById( "canvas_id" ); var Context = Canvas.getContext( "2d" ); Context.beginPath(); Context.strokeStyle = "red"; Context.arc( Canvas.width>>1, Canvas.height>>1, 50, Math.PI, Math.PI*2, false ); Context.arc( (Canvas.width>>1)+150, Canvas.height>>1, 50, Math.PI, Math.PI*2, true ); Context.stroke();

Im obigen Beispiel sieht man, dass der Endpunkt der Kurve mit dem Startpunkt der nächsten Kurve mit einem Strich verbunden wird. Weiterhin zeigt das Beispiel, dass mithilfe des letzten Parameters die Start- und Endpunkte in anderer Richtung verbunden werden.

Mit der Funktion arcTo( x0, y0, x1, y1, radius ) können wir eine Kurve zwischen zwei Koordinaten mit dem angegebenen Radius zeichnen. Wichtig dabei ist, dass bereits bestehende Unterpfade vorhanden sind, denn ansonsten tut die Funktion nichts. Ein simples moveTo() reicht dafür bereits aus.

  • Html
  • Javascript
  • Ergebnis
<html> <head></head> <body> <canvas id="canvas_id" width="600" height="200" style="border: 1px solid red;"></canvas> </body> </html>
var Canvas = document.getElementById( "canvas_id" ); var Context = Canvas.getContext( "2d" ); var xStart = 150; var yStart = 20; var xP1 = 150; var yP1 = 100; var xP2 = 50; var yP2 = 20; var radius = 30; Context.beginPath(); Context.strokeStyle = "blue"; Context.moveTo( xStart, yStart ); Context.arcTo( xP1, yP1, xP2, yP2, radius ); Context.stroke(); Context.fillStyle = "blue"; Context.fillRect( xStart, yStart, 10, 10 ); Context.fillStyle = "red"; Context.fillRect( xP1, yP1, 10, 10 ); Context.fillRect( xP2, yP2, 10, 10 ); Context.beginPath(); Context.strokeStyle = "red"; Context.moveTo( xP1, yP1 ); Context.lineTo( xP2, yP2 ); Context.stroke();

Wir zeichnen eine simple Kurve zwischen den beiden Koordinaten 150/100 und 50/20 mit dem Radius 50px. Dabei ist wichtig, dass sich die Kurve durch den letzten Pfadpunkt beeinflussen lässt. Verschiebt man also den Startpunkt, sowie die Kontrollpunkte P1 und P2, kann man sehen, wie sich die Kurve verhält.

Einen Pfad schließen

Mit der Methode closePath() können wir einen Pfad schließen. Dabei wird eine Linie vom letzten Punkt unseres Pfades zum Anfang gezogen:

  • Html
  • Javascript
  • Ergebnis
<html> <head></head> <body> <canvas id="canvas_id" width="600" height="200" style="border: 1px solid red;"></canvas> </body> </html>
var Canvas = document.getElementById( "canvas_id" ); var Context = Canvas.getContext( "2d" ); Context.beginPath(); Context.moveTo( 250, 50 ); Context.lineTo( 350, 50 ); Context.lineTo( 300, 150 ); Context.closePath(); Context.stroke();

Im obigen Beispiel zeichnen wir zwei Seiten eines Dreiecks und lassen uns die letzte Linie mithilfe der closePath() Funktion erstellen. Da der letzte Punkt unserer Unterpfade bei 300/150 liegt, wird von dort aus ein Strich zum Startpunkt 250/50 gezogen.

Einen Punkt im Pfad prüfen

Wenn wir wissen wollen, ob ein Punkt sich bereits in einem Pfad befindet, können wir die Funktion isPointInPath( x, y ) ausführen. Diese nimmt folgende Parameter an:

ParameterBeschreibung
xGibt die X-Koordinate des Punkts an.
yGibt die Y-Koordinate des Punkts an.
  • Html
  • Javascript
  • Ergebnis
<html> <head></head> <body> <canvas id="canvas_id" width="600" height="200" style="border: 1px solid red;"></canvas> </body> </html>
var Canvas = document.getElementById( "canvas_id" ); var Context = Canvas.getContext( "2d" ); Context.beginPath(); Context.rect( 20, 20, 200, 100 ); Context.stroke(); for( var x = 0; x < Canvas.width; x++ ) for( var y = 0; y < Canvas.height; y++ ) if( Context.isPointInPath( x, y ) ) Context.fillRect( x, y, 1, 1 );

Das Beispiel erstellt einen rechteckigen Pfad vom Punkt 20/20 mit den Maßen 200px/200px. Als nächstes prüfen wir jeden einzelnen Pixel unseres Canvas, ob dieser in unserem Pfad und damit im Rechteck liegt. Ist dies der Fall, wird dieser Punkt mithilfe der Methode fillRect() ausgemalt. Es spielt also keine Rolle, wie groß unser Rechteck ist, denn alle Punkte, die darin liegen, werden ausgemalt.

Eine quadratische Kurve zeichnen

Mit der Methode quadrativCurveTo( x0, y0, x1, y1 ) können wir eine quadratische Bezierkurve zeichnen. Diese Funktion nimmt folgende Parameter an:

ParameterBeschreibung
x0Die X-Koordinate des Kontrollpunktes.
y0Die Y-Koordinate des Kontrollpunktes.
x1Die X-Koordinate des Endpunktes.
y1Die Y-Koordinate des Endpunktes.
  • Html
  • Javascript
  • Ergebnis
<html> <head></head> <body> <canvas id="canvas_id" width="600" height="200" style="border: 1px solid red;"></canvas> </body> </html>
var Canvas = document.getElementById( "canvas_id" ); var Context = Canvas.getContext( "2d" ); Context.beginPath(); Context.moveTo( 20,20 ); Context.quadraticCurveTo( 100, 20, 20, 180 ); Context.stroke();

Diese Funktion benötigt zunächst einen vorangegangenen Punkt. Diesen können wir uns bereits mit der Methode moveTo() erstellen lassen. Im obigen Beispiel haben wir eine Kurve vom Ausgangspunkt 20/20 zum Endpunkt 200/20 gezogen. Die ersten beiden Parameter geben unseren Kontrollpunkt an. Wie dieser unsere Kurve beeinflusst, kann an folgendem Schaubild und ein wenig experimenteller Einstellung wesentlich besser verstanden werden, als jede Erklärung.

Quadratische Kurven - CodingLab

Eine Bezierkurve zeichnen

Mit der Methode bezierCurveTo( x0, y0, x1, y1, x2, y2 ) können wir eine Bezierkurve mit zwei Kontrollpunkten zeichnen. Die Methode benötigt einen vorangegangenen Unterpfadpunkt, welchen wir bereits mit einem moveTo() erzeugen können. Folgende Parameter nimmt diese Funktion an:

ParameterBeschreibung
x0Die X-Koordinate des ersten Kontrollpunktes.
y0Die Y-Koordinate des ersten Kontrollpunktes.
x1Die X-Koordinate des zweiten Kontrollpunktes.
y1Die Y-Koordinate des zweiten Kontrollpunktes.
x2Die X-Koordinate des Endpunktes.
y2Die Y-Koordinate des Endpunktes.
  • Html
  • Javascript
  • Ergebnis
<html> <head></head> <body> <canvas id="canvas_id" width="600" height="200" style="border: 1px solid red;"></canvas> </body> </html>
var Canvas = document.getElementById( "canvas_id" ); var Context = Canvas.getContext( "2d" ); Context.beginPath(); Context.moveTo( 20,20 ); Context.bezierCurveTo( 20,100, 200, 100, 200, 20 ); Context.stroke();

Im obigen Beispiel haben wir eine Bezierkurve von der Stelle 20/20 zum Punkt 200/20 gezogen. Dabei wirken sich die beiden Kontrollpunkte auf die Kurve aus. Das Verhalten dabei kann wie bei der quadratischen Kurve bereits festgestellt, am besten mit dem unteren Schaubild und austesten verstanden werden:

Bezierkurven - CodingLab

Als Tipp möchte ich hier noch erwähnen, dass man auf den Kreisbogen zwischen den Dreiecken achten sollte. Wie verhalten sich diese, wenn ich den Kontrollpunkt näher zum Start- bzw. Endpunkt verschieben und somit die Dreiecke spitzer bzw. breiter mache?

Unser Canvas beschneiden

Mithilfe der Pfad-Funktion clip() können wir unserem Canvas mitteilen, dass unser vorangegangener Pfad gleichzeitig unsere Anzeigefläche sein soll. Die Methode nimmt keine Parameter an und kann einfach anstelle von Render-Methoden ( stroke() etc. ) oder sogar nach dem erfolgreichen Anzeigen unseres Pfades ausgeführt werden:

  • Html
  • Javascript
  • Ergebnis
<html> <head></head> <body> <canvas id="canvas_id" width="600" height="200" style="border: 1px solid red;"></canvas> </body> </html>
var Canvas = document.getElementById( "canvas_id" ); var Context = Canvas.getContext( "2d" ); Context.beginPath(); Context.moveTo( 100, 0 ); Context.lineTo( 200, 0 ); Context.lineTo( 200, 200 ); Context.lineTo( 100, 200 ); Context.closePath(); Context.stroke(); Context.clip(); Context.beginPath(); Context.moveTo( 20,20 ); Context.lineTo( 100, 50 ); Context.lineTo( 200, 20 ); Context.lineTo( 300, 80 ); Context.lineTo( 250, 150 ); Context.lineTo( 50, 120 ); Context.lineTo( 20, 100 ); Context.closePath(); Context.stroke();

Im obigen Beispiel wurde ein simples Rechteck "geklippt" und anschließend ein Pfad erstellt. Wollen wir den ganzen Pfad betrachten, müssen wir lediglich die Funktion clip() auskommentieren. Weiterhin wurde extra ein stroke() ausgeführt, damit unsere Anzeigefläche auch visuell mit einem Rahmen zu sehen ist. Auch diese Methode kann also auskommentiert werden und die Methode clip() erfüllt ihre Funktion voll und ganz.