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ür Schritt eine mögliche Lösung.
Vorbereitung
Zuerst lege ich den benötigten HTML-Code an. Er enthält das <canvas>-Tag, also die "Leinwand", auf die ich später mit Javascript "zeichnen" werde. Ich speichere die Seite z.B. unter dem Namen "stars.html" (weitere Infos zum Umgang mit HTML-Dateien gibt es hier).
Im Head-Bereich verlinke ich die Javascript-Datei, in die ich den Code der Canvas-Animation einfügen werde. Die Datei befindet sich im gleichen Ordner wie die HTML-Datei.
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="canvas_stars.js"></script>
</head>
<body style="background-color:#1d1d1d">
<canvas id="myCanvas" width="100" height="100" style="background-color: #1d1d1d">
Your browser does not support the HTML5 canvas tag.</canvas>
</body>
</html>
Als nächstes öffne ich die Javascript-Datei und füge folgende Anweisungen ein:
var c = document.getElementById('myCanvas');
c.width = window.innerWidth;
c.height = window.innerHeight;
var ctx = c.getContext('2d');
var Point = {
x: 0,
y: 0
};
Der Code sorgt als Erstes dafür, dass das Canvas die volle Breite und Höhe des Browserfensters ("window") einnimmt. So lässt es sich besser in den Sternenhimmel eintauchen.
Mit dem Aufruf "getContext" erhalte ich ein Objekt, welches Anweisungen zum Zeichnen im Canvas entgegennimmt. Ich nenne es "ctx".
Zum Schluss lege ich einen Objektprototyp "Point" an, der die x- und y-Koordinaten eines Punktes im Canvas zusammenfasst. Wie Sie weiter unten gleich sehen werden, spare ich mir damit den Aufwand, für die x- und y-Koordinaten ständig separate Variablen verwenden zu müssen.
Schritt 1: Eine Menge von Sternen generieren
Ich wähle einen objektorientierten Programmieransatz, d.h. mein Code soll Eigenschaften und Verhalten von Objekten aus der realen Welt modellieren. Meine Objekte sind die Sterne. Jeder Stern besitzt in meiner "Weltanschauung" zunächst zwei Eigenschaften, nämlich seine Position im Canvas (x- und y-Koordinaten) und seine Breite (wenn der Stern als Quadrat dargestellt wird). Das Verhalten eines Sterns ist seine Fähigkeit, sich selbst an der richtigen Stelle als Quadrat in das Canvas einzuzeichnen.
Nach dieser Analyse kann ein Prototyp für Stern-Objekte programmiert werden:
var Star = {
position: null,
width:3,
draw: function() {
ctx.beginPath();
ctx.strokeStyle = 'hsl(60,100%,80%)';//Farbe des Sterns
//Stern als Quadrat zeichnen:
ctx.rect(this.position.x + c.width/2, this.position.y + c.height/2, this.width, this.width);
ctx.stroke();
ctx.closePath();
}
};
Da es sich nur um einen Prototypen und noch nicht um einen konkreten Stern handelt, ist die Position noch undefiniert (null).
Der Koordinatenursprung (x=0,y=0) befindet sich in der linken oberen Ecke des Canvas. Um ihn in die Mitte des Canvas zu verschieben, addiere ich beim Zeichnen des Quadrats auf die x- und y-Koordinate jeweils die Hälfte der Breite bzw. Höhe des Canvas.
Als nächstes programmiere ich eine Funktion, die 250 Stern-Objekte (die Anzahl können Sie ändern) generiert und in einem Array mit dem Namen "stars" speichert:
var stars = [];
function createStars() {
for (var i = 0; i< 250; i++) {
//Erstelle Objekt nach der Vorlage des Prototyps "Star":
var star = Object.create(Star);
star.position = Object.create(Point);
star.position.x = randomRange(-50, 50);
stars.position.y = randomRange(-50, 50);
stars.push(stars);
}
}
function randomRange(minVal,maxVal) {
return Math.floor(Math.random() * (maxVal-minVal-1)) + minVal;
}
Wie Sie sehen, wird die Position der Sterne zufällig generiert. Es ist wichtig, dass Positionen aus allen vier Quadranten des Koordinatensystems gewählt werden. Nur so ist es möglich, dass später die Sterne in alle vier Himmelsrichtungen schweben: Sterne im ersten Quadranten fliegen nach rechts oben, Sterne im zweiten Quadranten fliegen nach links oben usw..
Damit die generierten Sterne im Canvas angezeigt werden, brauche ich noch eine Funktion, die für alle Stern-Objekte die Funktion "draw" aufruft. Vorher wird mit dem Aufruf von "clearRect" das Canvas geleert.
function update() {
ctx.clearRect(0, 0, c.width, c.height);
stars.forEach(function(elem, i, arr) {
elem.draw();
});
}
createStars();
update();
Damit Sie das Ergebnis gleich sehen können, habe ich ein ausführbares Beispiel vorbereitet:
Während der Animation müssen die Sterne schrittweise ihre Position im Canvas ändern. Dabei soll der Eindruck entstehen, dass die Sterne auf den Betrachter zu schweben. Mit anderen Worten: die Sterne sollen in einem virtuellen 3D-Raum eine bestimmte Entfernung vom Betrachter besitzen, und diese Entfernung soll sich Schritt für Schritt verringern.
Die folgende Skizze veranschaulicht den Sachverhalt nach den Grundsätzen der Zentralprojektion oder der perspektivischen Projektion. Der Bildschirm wird durch eine senkrechte Linie dargestellt. Er entspricht gleichzeitig der y-Achse. Davor befindet sich der Augpunkt O, an dem sich der Betrachter befindet. Dahinter befinden sich die Punkte P1 und P2 im virtuellen Raum. Um diese Punkte auf den Bildschirm zu projizieren, müssen die Schnittpunkte P1' bzw. P2' der Geraden OP1 bzw. OP2 mit dem Bildschirm berechnet werden. Es ist bereits erkennbar, dass ein Punkt, der dem Bildschirm bzw. dem Betrachter näher steht, auf der y-Achse weiter oben abgebildet wird (das gleiche gilt auch für die x-Achse). In ähnlicher Weise verhält sich die Star-Trek-Intro: die Sterne schweben langsam auf die Bildschirmränder zu.
Um die Projektionskoordinaten eines Punktes wie z.B. P1 zu berechnen, kann folgende Verhältnisgleichung (Strahlensatz) genutzt werden: P1.y/D = P1'.y/D', sodass gilt: P1'.y = D'*P1.y/D
Im nächsten Schritt erweitere ich das Programm wie folgt:
Ich ergänze eine Konstante "d_strich" als Entfernung des Betrachters vom Schirm (ich wähle 150, den Wert können Sie ändern).
Ich ergänze eine Eigenschaft "d" im Star-Prototyp zur Festlegung der Entfernung des Sterns vom Betrachter.
Ich ergänze eine Funktion "project2d", mit der die Bildschirmposition P' eines Sterns P in Abhängigkeit von seiner Entfernung "d" berechnet werden kann.
Ich ändere die "draw"-Funktion so ab, dass der Stern P an die durch "project2d" berechnete Position P' gezeichnet wird.
Beim Initialisieren der Stern-Objekte ("createStars") erhält jeder Stern eine zufällig generierte Entfernung "d". Meine Entfernungen liegen zwischen 0 und 32 Pixel, Sie können die Werte natürlich ändern.
Den geänderten Code zeige ich hier:
Schritt 3: Animation - die Sterne bewegen sich auf den Bildschirm zu
Jetzt ist alles vorbereitet, um eine Animation zu starten. Dazu sind nur noch drei Schritte erforderlich:
Mit Hilfe der Canvas-Funktion "setInterval" veranlasse ich, dass meine Funktion "update" in einem bestimmten Intervall (z.B. alle 25ms) aufgerufen wird.
In der Funktion "update" ergänze ich in der for-Schleife eine Anweisung, um die Entfernung "d" des Sterns "elem" zu reduzieren (z.B. um 0.2 Pixel). Das bedeutet, dass alle 25ms die Entfernung jedes Sterns um 0.2 Pixel reduziert wird (sie bewegen sich also auf den Betrachter zu).
In der "draw"-Funktion veranlasse ich, dass ein Stern wieder auf die maximale Entfernung zurückgesetzt wird, sobald er den Rand des Canvas erreicht hat.
Hinweis: Wenn Sie mehrmals auf den "Ausführen"-Button klicken, kann es auf dieser Seite zu Problemen kommen.
So richtig schön sieht das Ganze noch nicht aus. Der 3D-Effekt wirkt erst dann, wenn sich Größe und Helligkeit der Sterne in Abhängigkeit von ihrer Entfernung ändern. Zu diesem Zweck berechne ich nun in der Funktion "draw" den Wert "percent", der angibt, wie viel Prozent der maximalen Entfernung der Stern bereits zurückgelegt hat. Ich nutze ihn, um die Breite und Helligkeit des Sterns anzupassen.
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...
Willkommen zum zweiten Teil meines Javascript-Canvas-Tutorials! Die Programmierung meiner fraktalen, ornamentalen Blumenranke tritt nun in die entscheidende Phase. Mit der animierten Sinuskurve habe ich im ersten Teil bereits die Grundform der Hauptranke definiert....
Sehr super gemacht. Find ich gut!!