Das Document Object Model, DOM

(Auszug aus "Das Einsteigerseminar SVG — Webgrafiken mit XML" von Helma Spona)

Die bisherigen Beispiele haben sich auf die Veränderung vorhandener Elemente in der Grafik beschränkt. Viel effizienter und nützlicher sind jedoch Skripte, die selbst Elemente hinzufügen, verschieben oder löschen.

Auch war bisher nur die Manipulation von Attributen ein Thema. Wenn Sie jedoch den Text eines <text>-Tags ändern möchten, nützt der Zugriff auf Attribute nichts. Sie müssen dazu auf den Inhalt des Tags zugreifen. Für all diese Zwecke verfügt eine SVG-Grafik, genau wie XML-Dateien, über ein DOM.

Wie Sie auf das DOM einer SVG-Grafik zugreifen, haben die vorstehenden Beispiele schon gezeigt. Sie benötigen zunächst ein onload-Attribut oder einen anderen Eventhandler, über den Sie auf irgendein Element der Grafik zugreifen können. Dann haben Sie auch automatisch Zugriff auf das übergeordnete SVG-Dokument. Die SVG-Grafik wird durch das SVGDocument-Objekt repräsentiert.

Das SVGDocument-Objekt entspricht jedoch nicht dem <svg>-Tag, sondern der kompletten Datei. Der <svg>-Tag ist als erstes Element des SVGDocument-Objekts zu verstehen und muss daher über die Methode getFirstChild( ) zurückgegeben werden. Mit der Anweisung svgdok.getFirstChild( ).getChildNodes( ).length ermitteln Sie bspw. die Anzahl der Elemente innerhalb des <svg>-Tags. Dieser wird von der Methode getFirstChild( ) zurückgegeben. Mit der Methode getChildNodes( ) wird dann eine Auflistung aller untergeordnete Elemente des <svg>-Tags festgestellt und deren Anzahl über die length-Eigenschaft ermittelt. Damit das Beispiel auch in Netscape funktioniert, wird die length-Eigenschaft nicht direkt, sondern über die getLength( )-Methode ermittelt. Diese Angaben reichen aus, um in einer einfachen Schleife auf alle Elemente der SVG-Datei zuzugreifen. Das zeigt das erste Beispiel.

Hinweis:
Analog zur Methode getFirstChild( ) gibt es eine Methode getLastChild( ), die das letzte der untergeordneten Elemente zurückgibt.

Um auf einzelne Elemente innerhalb der Grafik zugreifen zu können, gibt es natürlich Eigenschaften und Methoden. Die Methode getElementById wurde bereits verwendet, ermöglicht jedoch nur den Zugriff auf benannte Elemente. Da das Objektmodell einer SVG-Grafiken hierarchisch geordnet ist, können Sie sich jedoch durch alle Objekte der Grafik bewegen, ohne deren Namen und Typ kennen zu müssen. Über entsprechende Eigenschaften und Methoden sind Sie zudem in der Lage, ein <text>-Element von einem <circle>-Element und die eigentlichen Zeichnungselemente von versteckten Elementen zu unterscheiden. Das erste, einfache Beispiel zeigt dies. Es durchläuft alle Elemente der Grafik und setzt deren fill-Eigenschaft neu, wenn es sich um sichtbare Elemente der Grafik handelt.

Das Beispiel definiert einen Text, ein Rechteck und einen Kreis, die schwarz gefüllt werden. Das Rechteck wird jedoch gar nicht gefüllt und nur mit einer schwarzen Umrandung versehen. Beim Laden der Grafik wird dann die Funktion init ausgeführt. Der Variablen svgTag wird zunächst der <svg>-Tag als Objekt zugewiesen, über das danach auf dessen untergeordnete Elemente zugegriffen werden kann. Das erfolgt in einer for-Schleife, die eine Zählvariable i von 0 bis zur Anzahl der untergeordneten Tags zählt. Innerhalb der Schleife wird dann das einzelne Element mit der getChildNodes( )-Methode ermittelt. Dieser Methode wird die Zählvariable i übergeben, um damit das untergeordnete Element mit dem Index i festzustellen.

Hinweis:
Da alle Indizes bei 0 beginnen, läuft die Zählvariable i von 0 bis zu einem Wert, der kleiner als der von length gelieferte Wert ist.

Die Auflistung der Elemente, die Sie mit getChildNodes( ) ermitteln und durchlaufen, enthält neben den sichtbaren Elementen der Grafik auch unsichtbare Elemente. Beim Versuch, für diese Elemente das style-Attribut zurückzugeben und Eigenschaften neu zu setzen, tritt ein Laufzeitfehler auf. Sie müssen also sicherstellen, dass Sie nur auf Elemente zugreifen, die das erlauben. Sie können dazu mit der Methode getNodeType( ) den Typ des Elements abfragen. Die Methode gibt für alle sichtbaren Elemente den Wert 1 zurück, für andere den Wert 3. Sie dürfen somit nur die Elemente bearbeiten, für die die Methode den Wert 1 zurückgibt. Das lässt sich wie im Beispiel gezeigt mit einer einfachen if-Anweisung erreichen. Nun müssen Sie nur noch die Füllfarbe setzen. Wie das geht, wissen Sie bereits.

Hinweis:
Versuche haben gezeigt, dass die unsichtbaren Elemente dann entstehen, wenn Tags mit einem separaten Abschluss-Tag geschlossen werden. Die unsichtbaren Elemente repräsentieren dann die Abschluss-Tags der Elemente. Warum das so ist, ist nicht ganz klar. Sicher ist nur, dass es nicht dem DOM-Standard des W3C entspricht. Daher sollten Sie die hier gezeigte Methode verwenden, um unabhängig vom Vorhandensein dieser Elemente korrekt auf die sichtbaren zuzugreifen. Das sollte dann auch funktionieren, wenn andere Plug-Ins oder Browser diese Elemente nicht im DOM berücksichtigen.

<?xml version="1.0" encoding="iso-8859-1"?>
...
<svg width="320" height="300" onload="init(evt)">
  <script type="text/ecmascript">
    <![CDATA[
      var elem;
      var svgdok;
      var eingabe="";
      function init(evt)
      {
        var i=0;
        var svgTag;
        var styleAttr;
        svgdok=evt.getTarget().getOwnerDocument();
        svgTag=svgdok.getFirstChild();
        for (i=0;i<svgTag.getChildNodes()
          .getLength();i++)
        {
          elem=svgTag.getChildNodes(i);
          if (elem.getNodeType()==1)
          {
            styleAttr=elem.getStyle();
            styleAttr.setProperty("fill","blue");
          }
        }
      }
    ]]>
  </script>
  <text x="10" y="40">Textelement</text>
  <rect x="50" y="50" width="10" height="10" style="stroke:black;fill:none"/>
  <circle cx="120" cy="120" r="10" width="10" height="10" style="stroke:black;fill:black"/>
</svg>

Die gleiche Grafik vor und nach der Skriptausführung

Abbildung: Die gleiche Grafik vor und nach der Skriptausführung.

Möchten Sie nicht alle Elemente blau einfärben, sondern bspw. Textelemente rot, Kreise gelb und Rechtecke blau, können Sie auch das recht einfach bewerkstelligen. Dazu ist nur eine kleine Abwandlung der Funktion init notwendig. Sie fragen dazu die Eigenschaft NodeName des Elements mit der getNodeName( )-Methode ab. Sie liefert den Namen des Tags, also text für <text>-, rect für <rect>- und circle für <circle>-Elemente.

function init(evt)
{
  var i=0;
  var svgTag;
  var styleAttr;
  svgdok=evt.getTarget().getOwnerDocument();
  svgTag=svgdok.getFirstChild();
  for (i=0;i<svgTag.getChildNodes().getLength();i++)
  {
    elem=svgTag.getChildNodes(i);
    if (elem.getNodeType()==1)
    {
      styleAttr=elem.getStyle();
      if (elem.getNodeName()=="rect")
      {styleAttr.setProperty("fill","blue");}
      if (elem.getNodeName()=="text")
      {styleAttr.setProperty("fill","red");}
      if (elem.getNodeName()=="circle")
      {styleAttr.setProperty("fill","yellow");}
    }
  }
}

Diese Möglichkeiten, den Inhalt von SVG-Grafiken zu manipulieren, ist jedoch erst im Zusammenhang mit der dynamischen Erzeugung von Elementen interessant. Sie können nämlich mit Hilfe des DOM auch Elemente in die Grafik einfügen oder daraus löschen oder Text und andere Inhalte von Tags ändern. Wie das geht, erfahren Sie im nächsten Abschnitt.

   

<< zurück vor >>

 

 

 

Tipp der data2type-Redaktion:
Zum Thema SVG bieten wir auch folgende Schulungen zur Vertiefung und professionellen Fortbildung an:

Copyright © verlag moderne industrie GmbH 2001
Für Ihren privaten Gebrauch dürfen Sie die Online-Version ausdrucken.
Ansonsten unterliegt dieses Kapitel aus dem Buch "Das Einsteigerseminar SVG — Webgrafiken mit XML" denselben Bestimmungen wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

verlag moderne industrie GmbH, Justus-von-Liebig-Straße 1, D-86899 Landsberg/Lech, fon ++49 (0) 81 91 / 125 – 0, leserservice(at)mi-verlag.de