Am Beispiel des Malteserkreuzes, dessen Konstruktion auf der Seite "Anwendung ebener Transformationen" ausführlich beschrieben wird (rechts sieht man das Ergebnis), soll gezeigt werden, wie es gelingt, Bewegung in das Bild zu bringen:
Die prinzipielle Strategie für eine Animation kann wie folgt beschrieben werden:
Die Lage der Kurbel wird in der Funktion crank bei der Konstruktion des Malteserkreuzes durch eine Rotations-Transformation bestimmt, die mit dem Rotationswinkel phi0 festgelegt wird:
gi.trot (0 , L , phi0) ;
Die CanvasGI-Funktion trot arbeitet inkrementell, so dass bei jedem Aufruf eine zusätzliche Rotation hinzukommt. Es würde sich also anbieten, diese Funktion ständig mit einem DeltaPhi aufzurufen. Diese einfache Variante scheidet hier aus, weil verschiedene Rotationen (Kurbel und Malteserkreuz) zu verwalten sind. Deshalb wird folgende (besonders einfache) Strategie gewählt: Der Winkel phi0 für den Aufruf von trot wird jeweils um DeltaPhi erhöht, und vor jedem trot-Aufruf wird die gesamte Transform mit tinit "auf Null gestellt".
Deshalb wird der Winkel phi0 als Variable betrachtet, die nach jeweils einer bestimmten Zeit DeltaT um den Winkel DeltaPhi verändert wird. Der Bereich, in dem die globalen Variablen vereinbart sind, wird also zum Beispiel um diese beiden (hellblauen) Zeilen ergänzt
var phi0 = -Math.PI/3 ; var DeltaT = 50 ; var DeltaPhi = Math.PI/20 ;
In der Funktion init, die beim Start der Seite aufgerufen wird, und in der aus ihr gestarteten Funktion draw sind folgende minimalen Änderungen vorzunehmen (hellblaue Zeilen):
function draw () { gi.clearcanvas ("silver" , "black") ; // ... fuellt Canvas-Bereich mit Hintergrundfarbe // ("silver") und zeichnet schwarzen Rahmen crank () ; // ... zeichnet die Kurbel cross () ; // ... zeichnet das Malteserkreuz pivots () ; // ... zeichnet die Lager phi0 += DeltaPhi ; } function init () { gi = new canvasGI ("canvas") ; // Ein "CanvasGI-Objekt" wird erzeugt gi.setusercoordsi (-L , -L , L , L+R+Rs , 5) ; window.setInterval ("draw ()" , DeltaT) ; }
Das war nicht schwierig: Die Kurbel dreht sich |
Zwei Probleme sind zu lösen, um dem Kreuz die zur Kurbelbewegung passende Drehbewegung aufzuzwingen:
Die Funktion cross wird also um die folgenden (hellblauen) Zeilen ergänzt, die genau diese beiden Bedingungen realisieren:
function cross () { gi.tinit () ; if (phi0 > -Math.PI/3 && phi0 < Math.PI/3) { // Kurbel im Eingriff var psi = Math.atan ((-R * Math.sin(phi0))/(L - R * Math.cos(phi0))) - Math.PI/6 ; gi.trot (0 , 0 , psi) ; } gi.beginpath () ; ...
Weil der Winkel phi0 unbegrenzt wächst, würde die oben programmierte Abfrage nur bei der ersten Kurbelumdrehung funktionieren. Dieser Mangel wird geheilt durch das Rücksetzen des Winkels nach Erreichen einer vollen Umdrehung. Dies wird in der Funktion draw ergänzt (hellblaue Zeile):
function draw () { gi.clearcanvas ("silver" , "black") ; // ... fuellt Canvas-Bereich mit Hintergrundfarbe // ("silver") und zeichnet schwarzen Rahmen crank () ; // ... zeichnet die Kurbel cross () ; // ... zeichnet das Malteserkreuz pivots () ; // ... zeichnet die Lager phi0 += DeltaPhi ; if (phi0 > 3*Math.PI/2) { phi0 -= 2*Math.PI ; } }
Das hier entwickelte Programm kann als c_malteseranimation.html, in einem separaten Fenster gestartet werden. Hier findet man eine etwas erweiterte Version, die das Stoppen und Starten der Bewegung und die Änderung der Geschwindigkeit gestattet.
Empfehlung zum Weiterlesen:" Canvas3D: Projektion auf eine ebene Zeichenfläche".
Folgende Seiten werden als Einführung in die Benutzung des CanvasGI empfohlen: