Mein Fotoblog Blaustern Fotografie sollte mit einer animierten, wachsenden Blumenranke geschmückt werden. Das Ergebnis können Sie bereits im Fotoblog betrachten (nur für Bildschirme ab 900px Breite). In diesem zweiteiligen Tutorial erkläre ich, wie das Ornament programmiert ist. Der Aufbau der Ranke folgt dem Konzept der fraktalen Geometrie: Von der Hauptranke zweigen sich mehrere Seitenranken ab, die selbst genauso aussehen wie die Hauptranke. Jede Seitenranke verzweigt sich auf die gleiche Weise wie die Hauptranke. Dadurch entstehen neue Ranken, die sich wiederum verzweigen und so weiter und so fort - bis die festgelegte Obergrenze erreicht ist. Das Prinzip der fraktalen Geometrie beschreibt Christiane Hoffmann treffend:
[Es gibt, AP] eine innere Ähnlichkeit, d.h. eine geometrische Eigenschaft (auch genannt Homothetie), nach der ein Teil des Objektes dem Ganzen ähnlich ist.
Für die Umsetzung dieser Idee bietet sich das HTML-Element Canvas an. Im ersten Teil dieses Tutorials möchte ich einige Grundlagen der Canvas-Programmierung erläutern. Ich werde eine Möglichkeit zum Erstellen von Canvas-Animationen zeigen. Das Endergebnis wird eine animierte, modifizierte Sinuskurve sein, die später die Hauptranke der Pflanze bilden wird.
Mit Javascript auf der Leinwand (Canvas) zeichnen
Zuerst muss das <canvas>-Tag in die HTML-Seite eingefügt werden. Hier sehen Sie eine minimale HTML-Seite, in der lediglich ein Canvas mit einer Höhe und Breite von 100 Pixel angezeigt wird. Dem Canvas habe ich die ID "myCanvas" gegeben. Im Head-Bereich verlinke ich eine externe Javascript-Datei "canvas_growing_leafs.js", die sich im gleichen Ordner befindet wie die HTML-Datei.
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="canvas_growing_leafs.js"></script>
</head>
<body>
<canvas id="myCanvas" width="100" height="100" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>
</body>
</html>
Beispiel 1
In der Javascript-Datei können wir nun anhand der ID auf das Canvas-Element zugreifen. Ich lege die Linienfarbe "rot" fest und zeichne einen Pfad von der Position (0,0) an die Position (50,50) im Canvas-Koordinatensystem. Die Position (0, 0) befindet sich in der linken oberen Ecke. Die Position (50,50) befindet sich genau in der Mitte meiner 100 Pixel breiten Leinwand. Der erste Wert ist dabei die x-Koordinate (horizontale Achse im Koordinatensystem, Werte steigen von links nach rechts) und der zweite Wert die y-Koordinate (vertikale Achse, Werte steigen von oben nach unten). Drücken Sie auf "Ausführen", um das Ergebnis zu sehen. Eine Referenz der verwendeten Canvas-Methoden finden Sie bei w3schools.
Sie können den Code oben modifzieren. Tragen Sie einfach bei moveTo und lineTo andere Koordinaten ein, um sich mit dem Koordinatensystem vertraut zu machen!
Beispiel 2
Als nächstes möchte ich einen Punkt zeichnen. Ich interpretiere einen Punkt als sehr kurze horizontale Linie mit einer Länge von 1px:
Beispiel 3
Das obige Beispiel wird nun so modifiziert, dass die x- und y-Koordinaten jeweils einer Variable zugewiesen werden. Die Verwendung von Variablen ist eine Voraussetzung für das Animieren von Kurven im nächsten Abschnitt.
Animierte Kurven zeichnen
Ich möchte eine animierte Linie programmieren, die langsam von links (x=0) nach rechts (x=100) wächst. Sie soll das Canvas in der Mitte durchlaufen, d.h. y=50. Zu diesem Zweck fasse ich die Linie als Kombination von vielen kleinen, 1px langen Segmenten auf (vgl. Beispiel 3). Wir müssen dem Computer mitteilen, dass er Schritt für Schritt die einzelnen Segmente zeichnen soll. Zwischen der Ausgabe zweier Segmente soll dabei jeweils ein bestimmter Zeitabstand eingehalten werden (z.B. 50ms), damit der Nutzer beobachten kann, wie die Linie wächst.
In diesem Sinne liegt der Animation folgender Algorithmus zugrunde:
Setze x = 0, y=50.
Wiederhole bis Abbruch:
Zeichne ein Liniensegment an die Position (x,y).
Rücke auf der x-Achse um eine Position nach rechts, d.h. x = x + 1.
Beispiel 4
Meine Funktion draw führt die Schritte 1 und 2 des oberen Algorithmus aus. Die Wiederholung der beiden Schritte übernimmt die Canvas-Funktion setInterval. Sie erhält den Funktionsnamen draw sowie ein Zeitintervall in ms als Parameter. Sie kümmert sich darum, dass die Ausführung der Funktion draw ununterbrochen wiederholt wird, mit einer Pause von 50ms nach jedem Durchgang.
Es ist auch zu beachten, dass die Variable x außerhalb der Funktion draw deklariert wird (globale Variable), da sonst ihr Wert bei jedem Funktionsaufruf auf 0 zurückgesetzt werden würde.
Beispiel 5
Die Animation soll abgebrochen werden, wenn der rechte Rand des Canvas erreicht ist. Zu diesem Zweck wird die ID benötigt, die von der Funktion "setInterval" zurückgegeben wird. Ich speichere sie in der Variable "id". In der Funktion "draw" überprüfe ich nun, ob der x-Wert schon die Obergrenze erreicht hat. Wenn ja, dann rufe ich die Canvas-Funktion "clearInterval" auf und übergebe die ID als Parameter. Dadurch wird die Animation angehalten. Als Obergrenze hätte ich auch 100 (die Breite des Canvas) wählen können. Ich möchte aber, dass in diesem Beispiel deutlich zu sehen ist, wie die Animation anhält.
Beispiel 6
Das Programm lässt sich sehr leicht abwandeln, um viele verschiedene Kurven zu zeichnen. Dazu muss in Abhängigkeit vom aktuellen x-Wert der Wert für y anhand einer mathematischen Funktion berechnet werden. Mit der Funktion "y = x" erhalten wir z.B. eine Diagonale:
Beispiel 7
Jetzt zeichne ich den Graph einer quadratischen Funktion. Statt "x=x+1" schreibe ich hier "x=x+0.1". Die kleinere Schrittweite ist bei dieser Funktion notwendig, um Lücken im Graph zu vermeiden (ändern Sie den Code, um den Unterschied zu sehen). Die Abbruchbedingung habe ich modifiziert, damit die Funktion nicht über den unteren Rand hinauswächst.
Grundform der Hauptranke
Beispiel 8
Die Grundform meiner Ranke ist eine Sinuskurve. Das Aussehen der Kurve steuere ich mit den Parametern "amp" (Amplitude) und "freq" (Frequenz). Testen Sie verschiedene Werte! Der Parameter "y_trans" dient dazu, die Kurve um 150 Pixel nach unten zu verschieben (Translation).
Beispiel 9
Die Sinuskurve soll mit fortschreitenden x-Werten immer flacher werden. Sie soll also eine in Abhängigkeit von "x" abnehmende Amplitude besitzen. Eine Möglichkeit, dies umzusetzen, ist die Multiplikation der Amplitude mit einer Exponentialfunktion.
Beispiel 10
Zum Schluss setze ich noch ein kleines Blatt an das Ende der Ranke. Mein Blatt setzt sich aus einem oberen und einem unteren Bogen zusammen. Jeder Bogen wird durch einen Aufruf der Canvas-Funktion quadraticCureTo definiert. Tatsächlich gezeichnet werden die Bögen erst nach einem erneuten Aufruf von stroke.
Die Parameter der Funktion quadraticCurveTo bedürfen noch einer Erklärung. Konzentrieren wir uns auf den oberen Bogen des Blattes, d.h. auf den ersten Funktionsaufruf. Sie müssen wissen, dass sich der Canvas-"Zeichenstift" gerade an der Position befindet, an die er beim letzten Aufruf von lineTo gesetzt wurde. Das ist in unserem Fall die Position (x+1, y+y_trans). Diese Position wird von der Funktion quadraticCurveTo automatisch als Startpunkt der Kurve verwendet. Der erste Parameter der Funktion bezeichnet die Stützstelle, der zweite Parameter den Endpunkt der Kurve. Das nächste Bild zeigt den oberen Blattbogen mit eingezeichneten Start-, Stütz- und Endpunkten.
Mit dem zweiten Aufruf von quadraticCurveTo wird der untere Teil des Blattes gebildet. Beachten Sie, dass nach dem ersten Aufruf die Position unseres Canvas-"Zeichenstiftes" nun auf dem Endpunkt der ersten Kurve, d.h. bei (x+1+40, y+y_trans) steht! Die zweite Kurve wird automatisch von dieser Position aus gezeichnet. Wir müssen lediglich den Stütz- und den Endpunkt angeben. Der Stützpunkt liegt gegenüber vom Stützpunkt der ersten Kurve, d.h. bei (x+1+20, y+10+y_trans). Der Endpunkt entspricht dem Startpunkt der ersten Kurve, d.h. (x+1, y+y_trans). Die erste Kurve wird also von links nach rechts und die zweite Kurve von rechts nach links gezeichnet.
Das Resultat auf CodePen
Das Resultat des ersten Teils dieses Tutorials stelle ich auch auf CodePen zur Verfügung:
Mit Animationen in Javascript Canvas habe ich mich in den letzten Monaten schon mehrfach beschäftigt. Erst vor Kurzem bin ich dabei auf den Bereich der "Transformationen" in der Canvas-Bibliothek aufmerksam geworden. Dazu gehören u.a. die Funktionen
save()restore()translate()rotate()scale()
Mehr Informationen: https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Transformat...
Voriges Jahr habe ich bereits einen Beitrag über die Programmierung eines animierten Sternenhimmels mit Javascript Canvas geschrieben. Die Programmierung war zwar mathematisch interessant, aber recht aufwändig, da Canvas von Haus aus keine dreidimensionalen Koord...
Vor ein paar Monaten habe ich diesen animierten Tunnel programmiert:
See the Pen Simple 3d tunnel with curves by Anna Prenzel (@blaustern_fotografie) on CodePen.
Hintergrund: Vorher hatte ich (auf Anregung meiner Mama) den animierten Sternenhimmel programmiert, d...
Die Intros alter Star-Trek-Serien zeigen einen virtuellen Flug durch den Weltraum:
Ich mag diese Animation, denn sie ist einfach und trotzdem effektvoll. So etwas möchte ich mit Javascript Canvas programmieren. In diesem Tutorial erkläre ich Schritt f...