Colorloop: Zufallszahlen, Audio und Arrays

Anhand eines neuen Beispiels wollen wir unsere Kenntnisse über JavaScript, HTML und CSS vertiefen, anwenden und erweitern. Wir nennen das Projekt Colorloop. In diesem Projekt werden wir uns mehr auf audiovisuelle Effekte als auf Interaktion konzentrieren, aber wir werden dabei schon bekanntes Wissen verwenden und trainieren können und auch ein paar neue JavaScript-Features kennenlernen. Die Grundidee ist so: Zum Klang eines Musikstücks soll die Hintergrundfarbe des Browserfensters von einer zufällig bestimmten Farbe zur nächsten überblenden. Im Vordergrund werden kurz Schlagwörter angezeigt und dann durchgewechselt. Etwa so soll das aussehen:

Zunächst erstellen wir am besten den HTML-Markup, dieser wird in diesem Beispiel recht kompakt bleiben. Wir erstellen eine HTML5-Grundstruktur und stellen den Zeichensatz im <head> und in der Statusleiste unten von Komodo Edit auf "UTF-8". Außerdem weisen wir dem <body> die ID "farbe" zu, um ihn per Skript später ansprechen zu können:

Nun kümmern wir uns als erstes um die Musikuntermalung. Wir wollen eine mp3-Datei als Endlosschleife spielen lassen, mit dem seit HTML5 verfügbaren <audio>-Tag ist dies ohne größere Tricks, Skripte oder Plugins möglich. Der gemafreie Loop (der übrigens von Carl Cox stammt) ist hier auf diesem Server hochgeladen und kann als Quelle (src) verlinkt werden. Innerhalb des <audio>-Tags sollten noch die Flags "autoplay" und "loop" gesetzt werden, damit der Sound von selbst startet und unendlich oft wiederholt wird. Das ergibt den folgenden Markup:

Wenn Sie diesen Markup im Browser aufrufen sollten Sie die Musik hören. Sonst ist natürlich im Browserfenster noch nichts zu sehen. Fügen wir als nächstes gleich noch einen <div>-Container mit der ID "wort" für unsere Schlagwörter ein, auch wenn dieser zunächst leer bleibt. Außerdem laden wird die Google Font "Plaster" im <head>, da wir den visuellen Effekt der Schlagwörter durch eine außergewöhnliche Schrift verstärken wollen.

Nun sollten wir uns als nächstes um die Farbanimation kümmern. Dafür erstellen wir wieder ein Inline-Script unterhalb des <body>. Wir werden als erstes auf die schon bekannte Art und Weise das <body>-Element über dessen ID "farbe" selektieren:
document.getElementById("farbe");

Nun brauchen wir eine Möglichkeit, dem <body> eine beliebige Farbe zuzuweisen. Wir können nicht wie in unserem Beispiel mit der Uhr mit einer Klasse arbeiten - dann müssten wir ja im CSS so viele Regeln schreiben, wie es Farben gibt, das wäre viel zu aufwändig. Der richtige Weg läuft hier über die sogenannten "Inline-Styles". Es gibt nämlich auch außerhalb von Stylesheets die Möglichkeit, einzelnen Tags CSS-Regeln zuzuweisen: Innerhalb des Tags wird dabei z.B. festgelegt: <body style="background-color:#222222">. Um das generelle Styling einer Site vorzunehmen ist dies natürlich kein zu empfehlender Weg, da man mit diesen Regeln immer nur ein einzelnes Element stylen kann und der Markup zu sehr mit dem Styling vermischt wird. Interessant ist für uns aber die Möglichkeit, diese Inline-Styles dynamisch durch JavaScript zu erzeugen. Denn auf diesem Weg könnten wir dem <body> per Script generierte Farben zuweisen.  Bei unserem per JavaScript selektierten Element können wir über die Eigenschaft "style" einen beliebigen Wert für die Eigenschaft "backgroundColor" einstellen. Wir testen dies zunächst mit einer von uns vorher festgelegten Farbe (Voller Anteil 255 für Rot und 0 für die beiden anderen Kanäle):
document.getElementById("farbe").style.backgroundColor="rgb(255, 0, 0)";    

Bauen wir diese Anweisung nun in unser Skript ein:

Der Test im Browser zeigt, dass die Zuweisung der Farbe funktioniert. Inspizieren sie den <body>-Tag auch in den Entwicklertools - Sie sehen, dass eine entsprechender Inline-Style generiert wurde. Nun wollen wir aber ja eigentlich die Ausprägungen der Farbkomponenten Rot, Grün und Blau zwischen 0 und 255 mit zufälligen Werten in diesem Intervall versehen. Wir brauchen also eine Möglichkeit, in JavaScript Zufallszahlen zu generieren. Natürlich gibt es diese Funktion, da Zufallszahlen in allen Programmiersprachen ab und zu benötigt werden. Wir können dabei auf das Modul "Math" für mathematische Funktionen zurückgreifen. Math.random() erzeugt eine Zufallszahl zwischen 0 und <1. Da wir aber ja ganzzahlige Werte zwischen 0 und 255 benötigen, müssen wird die von Math.random() erzeugen Werte etwas umformen: Indem wir den erzeugen Zufallswert mit 256 multiplizieren (die Werte sind ja immer kleiner 1, s.o.) und das Ergebnis auf die nächste ganze Zahl abrunden, sollten wir die benötigten Werte erhalten. Das Abrunden erreichen wir mit der Funktion Math.floor(). Wir generieren auf diese Art und Weise unsere drei benötigten Zufallszahlen und speichern sie jeweils in eine Variable:

Aber das funktioniert natürlich so noch nicht, da wir mit den generierten Werten ja noch nichts angefangen haben. Wir müssen nun noch unsere statischen Farbwerte mit den Zufallswerten ersetzen, indem wir das Schema für das Einstellen der rgb-Werte mit den Variablenwerten kombinieren:
"rgb("+red+","+green+","+blue+")";

Durch die Kombination von Text mit den numerischen Zahlenwerten werden diese wieder in Text umgewandelt und das Ergebnis übergeben wir der Eigenschaft "backgroundColor" als Wert:

Wir testen wieder das erweitere Skript im Browser. Wenn wir die Seite nun wiederholt neue laden, werden per Zufall unterschiedliche Hintergrundfarben generiert und angezeigt. Nun müssen wir den Vorgang noch automatisieren und in einem vorgegebenen Intervall wiederholen. Die erforderliche Funktion setInterval() haben wir ja schon verwendet, insofern machen wir gleich den Umbau: Die Bestimmung der Zufallszahlen und die Zuweisung der Farbe müssen in eine Funktion gekapselt werden, die dann per setInterval() aufgerufen werden kann:

Wir gehen also analog zu unserem Beispiel mit der Uhr vor. Damit die erste Farbe nicht erst nach 2 Sekunden generiert wird, rufen wir sie zusätzlich einmal beim Laden der Seite auf mit "farbwahl();". Was nun noch anders ist als in der Vorlage: die Farben erscheinen plötzlich und werden nicht überblendet. Um das zu ändern, müssen wir gar nichts am JavaScript ändern, dies können wir über eine der neuen CSS3-Eigenschaften einstellen. Daher generieren wir nun ein Inline-Stylesheet und stellen für den <body> eine CSS3-Transition ein:
transition: all 2s;

Dadurch versucht der Browser alle Veränderungen von Eigenschaften ("all"), wozu auch die Hintergrundfarbe gehört, in 2 Sekunden ("2s") weich zu überführen. Im Fall einer Farbe geschieht dies durch eine Überblendung. Hier wieder das aktualisierte Skript:

Der obligatorische Test im Browser zeigt die große Wirkung dieser kleinen Änderung. CSS3-Transitions sind neben den CSS3-Animations sehr mächtige Tools, um den Look&Feel einer Website zu steigern.
Nun sollten wir uns noch um die Wörter kümmern, die zusätzlich angezeigt werden sollen. Zunächst stellt sich die Frage, wie wir diese Wörter am besten abspeichern sollen. Mit unserem bisherigen Wissen würden wir wohl jedes Wort in eine neue Variable speichern, z.B. wort1="Fashion"; wort2="Sports"; etc.
Das würde auch funktionieren, ist aber etwas umständlich, wenn wir z.B. viele Werte eingeben wollen oder sich die Anzahl öfter verändern sollte. Der bessere Weg ist hier ein Array

Arrays

Arrays gibt es wie Variablen in allen Programmiersprachen, nur werden sie teilweise unterschiedlich bezeichnet, z.B. als Listen oder Felder. Ein Array ist so etwas wie eine "bessere" Variable, denn man kann in einen Array nicht nur einen, sondern fast beliebig viele Werte speichern (Außerdem kann ein Array mehrere Dimensionen haben, aber für unsere Zwecke ist eine Dimension völlig ausreichend). Erstellen wir nun einen Array mit der Bezeichnung woerter in dem wir unsere Wörter speichern. Das funktioniert recht ähnlich wie bei Variablen:
var woerter = ["Fashion", "Sports", "Passion", "Fokus", "Faith", "Trust", "Vogue", "Brand"];

Unser Array woerter hat eine Länge von 8. Diese Länge können wir jederzeit auch über die Eigenschaft length abfragen:
var laenge = woerter.length;

Zentraler aber ist noch die Frage, wie wir nun auf die einzelnen Elemente eines Arrays zugreifen können. Dies geht über deren Indexposition. Die Elemente eines Arrays sind von 0 ab indiziert, d.h. durchnummeriert. In unserem Fall hat also "Fashion" die Position 0 und "Brand" die Position 7. Will man nun das erste Element ausgeben, geht das über den Ausdruck: woerter[0]. Das letzte erhält man entsprechend mit woerter[7]. Unabhängig von der genauen Länge erhält man das Element an der letzten Position eines Arrays über:
arrayname[arrayname.length-1]; //beachten Sie die Zählweise ab 0!

Wir werden die Anzeige der Wörter nun so lösen, dass diese nicht per Zufall aus dem Array gezogen werden (was mit unserem Wissen auch leicht zu lösen wäre), sondern der Reihenfolge des Arrays nach angezeigt werden, beginnend bei Indexposition 0 bis zur Position 7 dann wieder von vorne. Der grundlegende Aufbau ist dabei zunächst einmal analog zur Ziehung der Farben: Per setInterval() rufen wir die Funktion textwahl, die die Wörter aus dem Array holt, jede Sekunde auf. Innerhalb dieser Funktion müssen wir uns darum kümmern, dass wir jeweils ein anderes Wort (an einer anderen Indexposition) aus dem Array holen und in den <div>-Container mit der ID "wort" schreiben. Um bei jeder Ausführung der Funktion eine höhere Indexposition zu ziehen, verwenden wir eine Zählervariable, die wir beginnend bei 0 bei jedem Aufruf um 1 erhöhen (auch inkrementieren genannt). Bei der letzten Indexposition (Länge des Arrays minus 1) muss diese Zählvariable dann wieder auf 0 zurückgesetzt werden. Dafür verwenden wir eine if-Anweisung.

Fügen wir also diese Funktionalität unserem bisherigen Skript hinzu:

Wir testen das erweitere Skript im Browser. Das Skript funktioniert wie gewünscht, allerdings müssen wir noch etwas CSS hinzufügen, damit die Ausgabe so aussieht wie in der Vorlage:

Damit ergibt sich insgesamt folgender Markup:

Die Ausgabe im Browser entspricht nun der Videovorlage.