10.7    Erzeugen von SVG-Elementen mit JavaScript

Sie können mithilfe von JavaScript nicht nur auf vorhandene SVG-Elemente zugreifen, sondern auch neue SVG-Elemente erzeugen. Damit haben Sie die Möglichkeit, regelmäßig aufgebaute SVG-Grafiken mit vielen Elementen zu erzeugen.

Innerhalb des Programms in svg_erzeugen.htm werden in einem etwas verspielten Beispiel insgesamt 36 Rechtecke in zufälligen Farben in einem 6-mal-6-Raster angeordnet, siehe Abbildung 10.14.

SVG-Elemente, mit JavaScript erzeugt

Abbildung 10.14    SVG-Elemente, mit JavaScript erzeugt

Alle Rechtecke durchlaufen anschließend ähnliche Animationen: Sie werden zunächst nach rechts verschoben, anschließend zeitversetzt um 90 Grad gedreht (siehe Abbildung 10.15) und erhalten zuletzt eine andere, wiederum zufällige Farbe.

SVG-Elemente, mit JavaScript animiert

Abbildung 10.15    SVG-Elemente, mit JavaScript animiert

Es folgt zunächst der Code zur Erstellung des Startzustands mit ingesamt 36 Rechtecken:

<!DOCTYPE html><html><head><meta charset="utf-8">
<title>SVG, Elemente erzeugen</title>
<script>
      function erzeugen()
{
var svgCont = document.getElementById("idSVG");
var ns = "http://www.w3.org/2000/svg";
var farbArray = ["#ff0000", "#ffff00", "#00ff00", "#0000ff"];

for(let i=0; i<6; i++)
{
for(let k=0; k<6; k++)
{
/* Rechteck zum SVG-Container hinzu */
var re = document.createElementNS(ns, "rect");
var xWert = 20 + 40 * i;
re.setAttribute("x", xWert);
var yWert = 20 + 40 * k;
re.setAttribute("y", yWert);
re.setAttribute("width", "20");
re.setAttribute("height", "20");
var fillWert = farbArray[Math.floor(Math.random() * 4)];
re.setAttribute("fill", fillWert);
re.setAttribute("stroke", "#000000");
re.setAttribute("stroke-width", "2");
svgCont.appendChild(re);
...
}
}
}
   </script>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" id="idSVG" width="310px"
height="260px" style="border:1px solid black" />
<script>
      erzeugen();
   </script>
</body></html>

Listing 10.13    Datei »svg_erzeugen.htm«, Startzustand

Im Dokumentrumpf steht ein SVG-Container mit einer ID, der noch keine Elemente beinhaltet. In diesem Fall wird keine Endmarkierung benötigt, die Startmarkierung muss aber mit /> abgeschlossen werden.

Darunter wird die JavaScript-Funktion erzeugen() aufgerufen. Diese Reihenfolge stellt sicher, dass das HTML-Dokument mit dem SVG-Container geladen ist, bevor die SVG-Elemente erzeugt werden.

Innerhalb der Funktion erzeugen() werden zunächst einige Variablen besetzt. Die Variable svgCont verweist auf den SVG-Container, die Variable ns auf den Namensraum, der für die SVG-Elemente benötigt wird. Das Feld farbArray beinhaltet die vier möglichen Farben für die Auswahl mithilfe des Zufallsgenerators.

Die Anordnung der insgesamt 36 SVG-Elemente innerhalb eines 6 mal 6-Rasters wird mithilfe einer geschachtelten Schleife ermöglicht. Zur Erzeugung eines neuen SVG-Elements wird die Methode createElementNS() genutzt, mit der ein Element aus einem bestimmten Namensraum erzeugt werden kann. Die Methode erwartet zwei Parameter: Den Namensraum und den Typ des Elements, hier rect.

Die Attribute und ihre Werte werden dem neu erzeugten SVG-Element mithilfe der Methode setAttribute() zugewiesen. Dabei werden die Werte für die x- und die y-Koordinate abhängig von der aktuellen Zeile und der aktuellen Spalte innerhalb des 6 mal 6-Rasters ermittelt. Der Wert für die Farbe wird mithilfe des Zufallsgenerators und des zuvor erzeugten Felds festgelegt.

Nach Zuweisung aller Attribute wird das neu erzeugte Rechteck dem SVG-Container mithilfe der Methode appendChild() als Kindknoten untergeordnet.

Es folgt der Code für die Animationen. Er befindet sich vollständig innerhalb der geschachtelten Schleife, wird also jeweils für ein Rechteck ausgeführt:

...
/* Animierte Translation zum Rechteck hinzu */
var animX = document.createElementNS(ns, "animate");
animX.setAttribute("attributeName", "x");
animX.setAttribute("begin", "1");
animX.setAttribute("dur", "1");
animX.setAttribute("by", "50");
animX.setAttribute("fill", "freeze");
re.appendChild(animX);

/* Animierte Rotation zum Rechteck hinzu */
var animRot = document.createElementNS(ns,
"animateTransform");
animRot.setAttribute("attributeName", "transform");
animRot.setAttribute("type", "rotate");
var beginWert = 3 + 0.2 * i;
animRot.setAttribute("begin", beginWert);
animRot.setAttribute("dur", "1");
var fromWert = "0, " + (80+40*i) + ", " + (30+40*k);
animRot.setAttribute("from", fromWert);
var toWert = "90, " + (80+40*i) + ", " + (30+40*k);
animRot.setAttribute("to", toWert);
animRot.setAttribute("fill", "freeze");
re.appendChild(animRot);

/* Animierte Farbänderung zum Rechteck hinzu */
var animFill = document.createElementNS(ns, "animate");
animFill.setAttribute("attributeName", "fill");
animFill.setAttribute("begin", "6");
animFill.setAttribute("dur", "1");

/* Farbe muss sich ändern */
var fillToWert;
do
fillToWert = farbArray[Math.floor(Math.random() * 4)];
while(fillToWert == fillWert);
animFill.setAttribute("to", fillToWert);

animFill.setAttribute("fill", "freeze");
re.appendChild(animFill);
...

Listing 10.14    Datei »svg_erzeugen.htm«, Animationen

Zur Erstellung der animierten Translation wird ein neues SVG-Element des Typs animate mithilfe der Methode createElementNS() erzeugt. Nach Zuweisung der Attribute und ihrer Werte mithilfe der Methode setAttribute() wird die neu erzeugte Animation dem jeweiligen Rechteck mithilfe der Methode appendChild() als Kindknoten untergeordnet.

Zur Erstellung und Zuordnung der animierten Rotation werden wiederum die Methoden createElementNS(), setAttribute() und appendChild() genutzt. Das SVG-Element hat diesmal den Typ animateTransform. Damit die Rotation zeitversetzt erfolgt, wird der Wert für das Attribut begin individuell festgelegt, und zwar abhängig von der aktuellen Spalte innerhalb des 6 mal 6-Rasters. Bei den Werten für die Attribute from und to ist Folgendes zu beachten: Die Rotation erfolgt vom Startzustand 0 Grad bis zum Endzustand 90 Grad und jedes Rechteck dreht sich um sein eigenes (!) Zentrum.

Zur Erstellung und Zuordnung der animierten Farbänderung werden ebenso die Methoden createElementNS(), setAttribute() und appendChild() genutzt. Das SVG-Element hat diesmal wieder den Typ animate. Mithilfe einer do-while-Schleife wird sichergestellt, dass sich der neue Farbwert und der alte Farbwert auf jeden Fall unterscheiden.