Schön viel Grafik

Millionen von Flash-Plug-in-Besitzern können nicht irren: Grafisches Web ist ‘in’. Mit der vom World Wide Web Consortium verabschiedeten Scalable Vector Graphics lässt sich das sogar herstellerunabhängig erreichen - allerdings mit einem weiteren Plug-in.

In Pocket speichern vorlesen Druckansicht 35 Kommentare lesen
Lesezeit: 20 Min.
Von
  • Henning Behme
Inhaltsverzeichnis

Schon im Oktober 1996 hatte das World Wide Web Consortium (W3C) mit der Portable Network Graphics (PNG) versucht, anderen Bitmap-Grafikstandards etwas entgegenzusetzen, das definitiv nicht von irgendwelchen Patenten abhängt. Scalable Vector Graphics (SVG), vom W3C im September 2001 verabschiedet, betrifft dagegen den Bereich der 2D-Vektorgrafik, die unabhängig von der Skalierung dieselbe Qualität beibehält (anders als Raster- beziehungsweise Bitmap-Grafik).

1998 versuchten Firmen wie Macromedia und Microsoft mit der Vector Markup Language (VML) sowie Adobe, IBM, Netscape und Sun mit der Precision Graphics Markup Language (PGML) skalierbare Webgrafiken zu standardisieren. Über den Status einer W3C-Note kamen beide Ansätze jedoch nicht hinaus. Das Konsortium insgesamt kümmerte sich hingegen durchaus um dieses Thema und veröffentlichte im Oktober 1998 einen Entwurf für die Anforderungen an skalierbare Webgrafik (schon damals SVG genannt).

Zwar unterstützt Microsoft weiterhin die VML und hat sie in sein Betriebssystem integriert (siehe [1]), aber spätestens seit September 2001, dem Zeitpunkt der Freigabe von SVG durch das W3C, ist abzusehen, dass sich der Konsortiumsvorschlag durchsetzen dürfte. Gefördert hat Adobe das durch den kostenlosen SVG Viewer, der als Browser-Plug-in für die Windows, Mac- und Linux-Welt zu haben ist (allerdings müssen Linuxer mit einer etwas älteren Version vorlieb nehmen). Und schließlich Apache: Eins von deren vielen Projekten, Batik, enthält eine Art Werkzeugkasten für SVG, in dem sich unter anderem ein Viewer befindet. Mehr zu Tools bietet der Artikel ‘Bildlich gesprochen’ auf Seite 60.

Angesichts der Verbreitung, die Macromedias Flash mittlerweile genießt, stellt sich manchen vielleicht die Frage, ob ein weiteres Format überhaupt erforderlich ist. Dafür muss SVG schon etwas zu bieten haben - was die Sprache in der Tat tut.

Zuallererst ist sie nicht von irgendeinem Hersteller abhängig, sondern alle im W3C beteiligten Firmen und Institutionen haben die Chance, an der Weiterentwicklung von SVG mitzuwirken. Wichtiger noch: SVG-Anwendungen sind sowohl von Menschen als auch von Maschinen lesbar (kein Binärformat); woraus sich unter anderem ergibt, dass Suchmaschinen jedes SVG-Dokument durchforsten können, denn es enthält nichts als Text. Schließlich: SVG-Dateien lassen sich komprimiert übers Netz schicken und in anderen Dokumenten referenzieren, was aus 15 bis 20 KBytes schon mal 1400 Zeichen macht.

Version 1.0 der Sprache ist spezifiziert und zu mehr oder minder großen Teilen in Adobes Plug-in sowie Batik umgesetzt (dazu später mehr). Potenziell gilt demnach das, was für Flash spricht: die Verbreitung auf Millionen von Clients.

Es versteht sich fast von selbst: SVG ist XML. Für Version 1.0 existiert eine Dokumenttypdefinition (DTD), die die Struktur von SVG-Instanzen beschreibt. Zu den vorgesehenen Elementen gehören Linien, Rechtecke und beliebige Pfade, außerdem sind Filter definiert. Nicht zu vergessen: Mit SVG lassen sich Animationen realisieren und interaktive Anwendungen erstellen (um Filter und Animationen dreht sich der zweite Teil dieses Tutorials). Insgesamt kein Wunder, dass viele die Sprache auf dieselbe Stufe wie Flash stellen - oder gar darüber.

In diesem Tutorial soll es um eine Einführung gehen, die außer den grundsätzlichen Eigenschaften der Sprache an zwei Anwendungen vorstellt, was sich mit einfachen Mitteln erreichen lässt. Dass noch nicht alles mit allen Browsern beziehungsweise Werkzeugen funktioniert, ist zwar bedauerlich, aber das dürfte sich bald ändern.

Schön, dass SVG XML ist: Für dieses Tutorial dient deshalb ein schlichter XEmacs als Editor. Die Listings respektive Anwendungen sind mit dem Adobe-Plug-in unter Windows und Linux sowie mit Batik 1.5b4b unter Linux geprüft und die Screenshots aus deren Darstellung erzeugt worden. Das gilt insofern nicht für alle SVG-Seiten, als Batik kaum Animation kennt und Adobes Linux-Plug-in über Transformationen stolpert (siehe unten).

Damit der eigene Webserver SVG-Instanzen korrekt ausliefern kann, sind zwei Voraussetzungen zu erfüllen: Die Dokumente müssen den richtigen MIME-Typ haben, und der Webserver muss das ‘wissen’. Dazu reicht es aus, wenn die Konfigurationsdatei (bei Apache: httpd.conf) die folgende Zeile enthält:

AddType image/svg+xml  .svg .svgz

Scripts, wie sie im dritten Teil des Tutorials vorkommen, müssen den Content-Type dezidiert setzen. Dass in obiger ‘AddType’-Zeile außer der Endung .svg noch .svgz steht, bewirkt, dass der Apache außer ‘normalem’ komprimiertes SVG ebenfalls korrekt ausliefert. Für erste Versuche zu Hause (= ohne Webserver) reicht es, eine SVG-Datei mit einem Browser (Plug-in vorausgesetzt) zu laden.

Grundsätzlich sieht jedes SVG-Dokument aus wie viele andere XML-Instanzen. Listing 1 enthält eine vollständige SVG-Seite. Rot gekennzeichnet ist die optionale Referenz des externen Stylesheet (CSS), blau eingefärbt der Namensraum XLink, der bei Hyperlinks anzugeben ist (für das SVG-Plug-in ist er nicht erforderlich, für Batik schon). Im Folgenden enthalten die Listings aus Platzgründen die ersten Zeilen (XML-Prolog, Stylesheet-Referenz und Dokumententyp) nicht, sondern lediglich den ‘reinen’ SVG-Part. title und desc sind optional; Erstere können Anwendungen in der Kopfzeile darstellen (Adobes Plug-in tut es allerdings noch nicht unter Linux). Ebenfalls optional ist defs. Dort kann man, wie das Kürzel zum Ausdruck bringt, Definitionen unterbringen, um sie später zu referenzieren - insbesondere, wenn man beispielsweise ein Element häufig benutzen will.

Mehr Infos

Listing 1: Grafische Basisformen

<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>

<?xml-stylesheet href="my.css" type="text/css"?>

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">

<svg width="500" height="500" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<title>Beispiel 1</title>
<desc>Beispiel: grafische Primitive</desc>
<!-- optional: title, desc, defs, metadata -->
<title>Grafische Basisformen</title>
<desc>Grafisches Ruestzeug: Rechteck, Kreis, Ellipse,
Linie, Pfad</desc>
<defs>
<style type="text/css"><![CDATA[
text { font-family:sans-serif;font-size:10;
font-weight: bold; fill:rgb(102,153,102)}
]]></style>
</defs>

<text id="text01" x="50" y="10">
Zwei Rechtecke, eins gerahmt, eins abgerundet</text>
<rect x="10" y="30" width="100" height="30"
style="fill: #669;stroke: #000000;stroke-width:2"/>
<rect x="200" y="30" width="100" height="30"
rx="5" ry="5"
style="fill:rgb(102,102,153)"/>


<text id="text02" x="50" y="100">Kreis und Ellipse</text>
<circle cx="50" cy="130" r="20"
style="fill:rgb(102,153,102)"/>
<ellipse cx="250" cy="130" rx="50" ry="10"
style="fill:rgb(102,153,102)"/>
<line x1="10" y1="180" x2="300" y2="180"
style="stroke:rgb(102,102,153); stroke-width: 0.7"/>

<text id="textlinie" x="305" y="185">Linie</text>
<polyline points="30 220 35 230 50 240 80 210 150 250 300 240"
style="fill: none; stroke: #333333;"/>

<text id="textpoly" x="305" y="245">zackige Linie (polyline)</text>
<polygon points="50,300 110,270 170,300 110,330 50,300"
style="fill: #339966"/>

<text id="textpath" x="305" y="300">Polygon</text>
<path d="M220,350 L200,350 L200,450 L220,450 L220,400
L260,450 L280,450 L240,400 C280,380 275,350 220,350"
style="stroke: #663333; fill: none;"/>
<path d="M120,350 L100,350 L100,450 L120,450 L120,400
L160,450 L180,450 L140,400 Q180,350 120,350"
style="stroke: #663333; fill: none;"/>
<text id="textpath" x="305" y="400">Pfade</text>
<text id="textpath2">
<tspan x="55" y="480">m. quadr. Bezierkurve</tspan>
<tspan dx="50" y="480">m. kub. Bezierkurve</tspan>
</text>n>
</svg>

Als Grafiksprache muss SVG die nötigsten Primitive enthalten, ohne dass man sie erst zu programmieren hat. Dazu gehören rect, line, polyline, circle, ellipse, polygon und path. Weitere sind für eine künftige Version vorgesehen. All diese (leeren) Elemente können Entwickler über Attribute steuern. Nicht nur, was x- und y-Werte sowie Breite und Höhe oder Radien angeht, sondern auch hinsichtlich der Füll- (fill) sowie Strichfarbe (stroke) und der Strichdicke (stroke-width) sowie des Deckungsgrades (opacity) von Strich- und Füllfarbe.

Wären den Elementen in Listing 1 nicht unterschiedliche y-Werte zugeordnet, lägen sie allesamt übereinander. Nach dem so genannten Painter's Model überdeckt das später ‘Gemalte’ das Frühere.

Listing 1 und Abbildung 1 zeigen ein paar der Grundformen, mit und ohne Striche. Zu beachten ist bei der Strichbreite immer, dass etwa die eines Rechtecks dessen ‘Rahmen’ sprengt, insofern sie nur zu 50 % innerhalb des Rechtecks bleibt. Die Stilanweisungen finden sich, wie von HTML her vielleicht bekannt, im Kopf der Datei, der hier allerdings nicht gekennzeichnet ist. Sicherheitshalber sollten style- und script-Elemente als CDATA-Sektion gekennzeichnet sein, für den Fall, dass etwa ein Kleiner-Zeichen vorkommt. title und desc gibt ein Browser ebenso wenig aus wie den Inhalt von defs und metadata. Alle text-Elemente haben infolge der Vorgabe einen Grünton als Farbe.

Parameter wie x, y, width und height, die in rect vorkommen, dürften einleuchten. Zusätzlich kennt das Rechteck rx und ry, worüber sich seine Ecken abrunden lassen. Bei Kreisen und Ellipsen geben cx und cy den Mittelpunkt an, nur hat die Ellipse zwei Radien.

Für alle Elementen können Designer Stileigenschaften auf unterschiedliche Weise definieren. Wie bei HTML können Autoren Vorgaben innerhalb der Elemente machen, wie das in den grafischen geschehen ist:

<rect ... style="..."/>

Von der Notation her sind für Properties wie fill und stroke zwei Varianten erlaubt: die aus CSS bekannte, mit style= eingeleitete, sowie eine XML-Variante

<rect ... fill="..." stroke="..."/>

in der die Eigenschaften als Attribut fungieren und jedes für sich einen Wert bekommt. Darüber hinaus kann man Stilanweisungen in eine externe Datei schreiben und mit der Anweisung in Listing 1 (rot hinterlegt) einbinden.

Vorsicht ist geboten: Inline-Stilanweisungen mit <rect ... style="..."/> oder durch das Element style wie am Anfang von Listing 1 haben immer Vorrang vor Anweisungen durch XML-Attribute (= überschreiben sie).

Gegenüber rect, circle, polyline und polygon erscheint das Element path erheblich spannender, denn mit diesem Element lassen sich beliebige grafische Formen realisieren. Nebenbei: Primitive wie rect sind nichts anderes als Vereinfachungen von path für den Komfort der Entwickler.

Für SVG-fähige Browser geht es hier zur SVG-Ansicht (formen.svg).

Grafische Grundformen stellt SVG zur Verfügung, für komplexe gibt es path - ganz unten (Abb. 1 und Listing 1).

Pfade haben als wichtigstes Attribut d (data), das die vorzunehmenden Bewegungen des ‘Stiftes’ enthält. Nur hier geht SVG im Grunde völlig un-XMLisch vor, denn die Daten sind nicht strukturiert. PostScript-Kenner dürften den Inhalt des d-Attributs interessiert betrachten, da er nicht allzu weit von der Seitenbeschreibungssprache entfernt ist.

Für SVG-fähige Browser geht es hier zur SVG-Ansicht (paths.svg).

Mehr Infos

Listing 2: Pfad - L und l

<path d="M10 10L100 100L200 30L250 100"
style="stroke: #333399; stroke-width: 1; fill: none;"/>
<path d="M10 15l90 90l100 -70l50 70"
style="stroke: #993333; stroke-width: 1; fill: none;"/>

Ohne in diesem Punkt erschöpfend sein zu können, seien ein paar der Befehle, die sich im Attribut d ‘verbergen, angerissen. Als Erstes ist M (moveto) zu nennen, Ausgangsbasis eines Pfades. Listing 2 enthält zwei Pfadbeschreibungen, die Abbildung 2 wiedergibt: zwei parallele Linien, im ersten Fall durch L, im zweiten durch l eingeleitet. Hier wie bei den anderen Befehlen unterscheiden sich Groß- und Kleinbuchstaben dadurch, dass die großen absolute Koordinaten angeben, die kleinen hingegen relative. Der Kasten ‘path: Wege für Pfade’ enthält die gebräuchlichsten Kommandos (aber nicht alle; der Bogen - A/a für arc - fehlt beispielsweise).

path:Wege für Pfade
Befehl Bedeutung
M 10 10 gehe zu x=10, y=10
m 10 10 gehe zu x=jetzt+10, y=jetzt+10
L 10 100 Linie zu x=10, y=100 ziehen
l 10 10 Linie zu x=jetzt+10, y=jetzt+10
H 100 horizontale Linie zu x=100, y=jetzt
h 100 horizontale Linie zu x=jetzt+100, y=jetzt
V 100 vertikale Linie zu x=jetzt, y=100
v 100 vertikale Linie zu x=jetzt, y=jetzt+100
Q 140 150, 160 30 quadratische Bézier-Kurve mit Anfasser (x=140, y=150) und Zielpunkt
q 140 150, 160 30 dito relativ zum Bezugspunkt
C 150 150,180 170,300 40 kubische Bézier-Kurve mit zwei Anfassern und einem Zielpunkt
c 150 150,180 170,300 40 dito relativ zum Bezugspunkt
T 100 100 quadratische Bézier-Kurve mit gespiegeltem Anfasser
T 100 100 dito relativ zum Bezugspunkt (ausgehend vom letzten)

Wie sich der Unterschied zwischen absolut und relativ auswirkt, zeigen Listing 3 und Abbildung 3. Die beiden kubischen Bézier-Kurven unterscheiden sich lediglich in der vertikalen Anordnung; abgesehen davon, ergibt die zweite Pfadbeschreibung dieselbe Kurve wie die erste. Nur relativ kodiert, immer mit Bezug auf den durch M erreichten Punkt.

Für SVG-fähige Browser geht es hier zur SVG-Ansicht (bezier.svg).

Mehr Infos

Listing 3: Kubische Bézier-Kurven

<path d="M200 10 C150 150,180 170,300 40"
style="stroke: #333399; stroke-width: 1; fill: none;"/>
<path d="M200 210 c-50 140,-20 160,100 30"
style="stroke: #333399; stroke-width: 1; fill: none;"/>

Auch bei Bézier-Kurven existiert der Unterschied zwischen Groß- und Kleinschreibung: absolute beziehungsweise relative Koordinaten (Abb. 3 und Listing 3).

Dass SVG ein Vektorformat ist, hält die Sprache nicht davon ab, JPEG- und PNG-Bitmap-Grafiken einzubinden - mit dem Element image:

<image xlink:href="mypicture.png" width="150" height="150"/>

Außerdem bietet image die bislang einzige Möglichkeit, SVG-Module in beliebige Dateien zu integrieren. Natürlich musste das Logo der iX für diesen Zweck herhalten. Es lag als EPS vor, und durch Adobes Illustrator war eine SVG-Variante, wie sie Abbildung 4 zeigt, schnell erstellt - ein ‘Speichern als SVG’ genügt. Zwar ist die SVG-Datei um einiges schlanker als das EPS-Original in mehreren Varianten (zwischen 50 und 200 KByte), aber mit 20 KByte immer noch umfänglich.

Für SVG-fähige Browser geht es hier zur SVG-Ansicht (ix.svg).

Mehr Infos

Listing 4: Logo-Stationen

<path i:knockout="Off" fill="none" stroke="#0C419A"
stroke-width="12" stroke-linecap="round" stroke-line-join="round" d="
M120.966,24.299 H89.318 l14.368,49.51
l-69.509,101.74 h31.648l47.763-69.315
l10.096,35.92 h31.648 l-19.804-68.15 l33.978-49.705
h-31.842 L125.82,41.58 L120.966,24.299z"/>
<!-- ... -->
_____________________________________________________

<defs>
<symbol id="ixlogo">
<path d="M120.966,24.299 H89.318 l14.368,49.51
l-69.509,101.74 h31.648 l47.763-69.315
l10.096,35.92 h31.648 l-19.804-68.15
l33.978-49.705 h-31.842
L125.82,41.58 L120.966,24.299z"/>
<!-- ... -->
</symbol>
</defs>
<use xlink:href="#ixlogo"
style="stroke: #0c419a ; stroke-width: 12;"/>
<!-- ... -->

Durch das Element symbol lässt sich eine Grafik wie das aus lauter Pfaden bestehende iX-Logo drastisch verkleinern (Abb. 4 und Listing 4).

Mehrere Optimierungsversuche führten dazu, dass sich das Logo auf knapp 3 KByte reduzieren ließ (siehe den Ausschnitt in Listing 4). Was den Durchbruch brachte, war das SVG-Element symbol, das die drei Pfade des Logos - ‘i’, ‘X’ und ‘i’-Punkt - zusammenfasst, sodass zwei Dutzend use-Zeilen ausreichen, um es zu zeichnen (im unteren Teil von Listing 4). symbol stellt die Anwendung nicht dar; erst die Referenz durch use xlink:href= bewirkt die Ausgabe.

Für diejenigen, die solche Exporte unternehmen wollen, dürfte das heißen, oft selbst Hand anlegen zu müssen, um die Dateigrößen in Grenzen zu halten. Illustrator optimiert in Fällen wie diesem nicht.

Das oben erwähnte Element image hat einen weiteren wichtigen Aspekt von SVG ins Spiel gebracht, und im gerade benutzten use kommt er ebenfalls vor: das Linking. SVG kennt wie HTML das Element a, aber andere können ebenfalls Verweise enthalten - wie oben gesehen.

Im Unterschied zu herkömmlichem HTML muss SVG sich auf XLink beziehen, weswegen in Listing 1 der blau eingefärbte Block vorhanden ist. Er definiert für das SVG-Element den Verweisnamensraum. Und da er xmlns:xlink heißt, muss ein Verweis vor dem href das xlink samt Doppelpunkt haben. Adobes Plug-in stolpert zwar nicht, wenn der Namensraum fehlt, Batik erwartet jedoch die Referenz auf den Namensraum.

Bis auf Weiteres beschränken sich die Verweise auf den so genannten einfachen Link. Erweiterte, wie sie die XLink-Spezifikation vorsieht, sind noch Zukunftsmusik.

Da es mit SVG so einfach ist, kleinere Grafiken zu erzeugen, bietet es sich an, sie in Webdokumenten einzubinden. Spätestens hier fangen die Schwierigkeiten für Benutzer von Mozilla 1.0 an. Weder das in der HTML-Spezifikation vorgesehene object noch das veraltete embed funktionieren; stattdessen verabschiedet sich der Browser ins Nirwana. Prinzipiell ist die folgende Schreibweise richtig:

<object data="helloworld.svg" type="image/svg+xml" width="300" height="200"></object>

Opera 6 zeigt immerhin Dateien mit embed-Element an, der IE beide. Da ist sicherlich noch nachzuarbeiten, vor allem bei Mozilla. Um solchen Inkompatibilitäten aus dem Wege zu gehen, folgen hier nur reine SVG-Listings.

Bevor es im zweiten Teil des Tutorials fast ausschließlich um grafische Finessen geht, soll eine Miniaturanwendung zunächst etwas anderes verdeutlichen: dass SVG sich durchaus eignet, anstelle von HTML für die Erstellung einer ganzen Webanwendung, wenn nicht einer Site zu dienen. Es geht um die Erzeugung von SVG aus XML-Daten eines anderen Dokumenttyps. Dabei kommen ein paar weitere Eigenheiten der Sprache zum Tragen.

Eine Anwendung oder Site völlig in SVG zu gestalten, lohnt sich für diejenigen, die das Web grafisch ausrichten wollen. Möglichst genaue Positionierung aller Elemente und daraus resultierende Kontrolle des Designers über das Ergebnis sind in solchen Fällen essenziell.

Die einfache Struktur der SVG-Zeittafel, die teilweise auf Daten basiert, die das W3C unter www.w3.org/Graphics/SVG/ vorhält, gibt ein Ausschnitt aus der DTD wieder (Listing 5). Ist eine Sammlung von Ereignissen vorhanden, fehlt nur noch das XSLT-Script, das die XML-Daten in ein anderes Format, in diesem Falle SVG, wandelt.

Mehr Infos

Listing 5: Ausschnitt aus DTD

<!ENTITY % inline "acro|emph|q|ref|progname|company|
person|org" >
<!ELEMENT timeline ( intro*, year+, sources? ) >
<!ELEMENT year ( event+ ) >
<!ELEMENT event ( day?, month, what+ ) >
<!ELEMENT para ( #PCDATA | %inline; )* >
<!ELEMENT day ( #PCDATA ) >
<!ELEMENT month ( #PCDATA ) >
<!ELEMENT what ( #PCDATA | %inline; )* >

XSL-Transformationen können nicht nur HTML aus XML generieren, sondern es kann sich um ein beliebiges Format handeln (zu XSLT siehe das Tutorial aus dem Jahre 2001 [2]).

Um für jedes Jahr eine SVG-Datei zu produzieren, ist ein Stylesheet erforderlich, vorausgesetzt, man verwendet einen XSLT-Prozessor, der mehrere Ausgabedateien schreiben kann. Hier kommt deswegen Michael Kays Saxon zum Einsatz. Allerdings die ältere Version 6.0.1, die nicht wie 7.x auf XPath/XSLT 2.0 basiert, denn beide sind noch nicht verabschiedet.

Listing 6 beinhaltet ein paar Fragmente aus diesem Stylesheet, die Saxons Arbeit beeinflussen. Am Anfang steht der übliche XML-Prolog, es folgt in xsl:stylesheet die Definition wichtiger Namensräume. Der von SVG (xmlns="http://www.w3.org/2000/svg") ist hier der Default, weswegen in der Folge SVG-Elemente ohne Vorsatz stehen dürfen: svg statt svg:svg oder Ähnlichem.

Die beiden Variablen benennen das Verzeichnis, in dem die SVG-Dateien ‘landen’ sollen, beziehungsweise den (Back-)Slash als Trenner zwischen Verzeichnis und Dateinamen. Das erste Template passt auf das Root-Element timeline und sorgt dafür, dass Saxon (nur) alle Jahre (year) verarbeitet.

Im Template für das Jahr, dessen Mantel Listing 6 enthält, bekommt die Variable thisyear den Wert des Attributs which zugewiesen, und Saxon erzeugt durch saxon:output für jeden unterschiedlichen Wert (jedes Jahr) eine eigene Datei: svg/xxxx.svg. Die eigentliche Arbeit steckt in Listing 7 und 8. Sie erzeugen mehrere geschachtelte svg-Elemente, die einen Frame-artigen Seitenaufbau suggerieren, wie Abbildung 5 zeigt.

Für SVG-fähige Browser geht es hier zur SVG-Ansicht (pseudoframes.svg).

Mehr Infos

Listing 6: XSLT-Rahmen

<?xml version="1.0" encoding="ISO-8859-1"?>

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/2000/svg"
xmlns:saxon="http://icl.com/saxon"
xmlns:xlink="http://www.w3.org/1999/xlink">
<xsl:variable name="dir">svg</xsl:variable>
<xsl:variable name="filesep"
select="system- property('file.separator')"/><xsl:template match="/time-line">
<xsl:apply-templates select="year"/>
</xsl:template>

<xsl:template match="year">
<xsl:variable name="thisyear" select="@which"/>
<saxon:output file="{$dir}{$filesep}{$thisyear}.svg"
method="xml" indent="yes"
doctype-public="-//W3C//DTD SVG 20010904//EN"
doctype-system="http://www.w3.org/2000/svg"
encoding="ISO-8859-1">
<!-- Verarbeitung der einzelnen Jahre -->
</saxon:output>
</xsl:template>

<!-- weitere Templates -->
</xsl:stylesheet>
Mehr Infos

Listing 7: XSLT: Erzeugung der SVG-Seiten

<svg width="100%" height="100%"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<rect width="100%" height="100%"
style="fill: #006699; stroke: none;"/>
<svg width="130" height="100" x="0" y="0"> <!-- logo -->
<rect width="100%" height="100%"
style="fill: #006699; stroke: none;"/>
<g width="175.5" height="181.5"
transform="scale(0.5) translate(30,50)">
<image xlink:href="ix.svg" width="130" height="100"/>
</g>
</svg>
<svg height="100" x="130" y="0"> <!-- appname -->
<rect width="100%" height="100%"
style="fill: #006699; stroke: none;"/>
<switch>
<text systemLanguage="de" x="80" y="80"
style="font-family: sans-serif; fill: #ccccff;
font-weight: bold; font-size: 24pt;">kleine svg-geschichte</text>
<text systemLanguage="en" x="80" y="80"
style="font-family: sans-serif; fill: #ccccff;
font-weight: bold; font-size: 24pt;">svg&apos;s history</text>
</switch>
</svg>
<svg x="0" y="100" width="130"> <!-- menu -->
<rect width="100%" height="100%"
style="fill: #006699; stroke: none;"/>
<g transform="rotate(-90) translate(-180, 120)">
<text x="0" y="0"
style="fill: #ccccff; font-family: sans-serif;
font-size: 36pt; font-weight: bold">
<xsl:value-of select="$thisyear"/>
</text>
<line x1="0" y1="4" x2="123" y2="4"
style="fill: #ccccff; stroke: #ccccff; stroke-width: 1;"/>
</g>
<line x1="85" y1="170" x2="85" y2="500"
style="fill: #ccccff; stroke: #ccccff; stroke-width: 0.5;"/>
</svg>
<svg x="130" y="100"> <!-- haupttext -->
<rect width="100%" height="100%"
style="fill: #006699; stroke: none;"/>
<!-- verarbeitung der ereignisse -->
<xsl:apply-templates select="event"/>
<text x="50" y="300" style="fill: #ccccff;
font-family: sans-serif; font-size: 10pt; font-weight: bold;">
<xsl:for-each select="//year">
<a xlink:href="{@which}.svg">
<tspan dx="30" y="300">
<xsl:value-of select="@which"/>
</tspan>
</a>
</xsl:for-each>
</text>
<text id="note" x="80" y="325" style="fill: #cccc00;
visibility: hidden;">note = (just a) note</text>
<!-- mehr unsichtbare text-elemente -->
</svg>
</svg>
Mehr Infos

Listing 8: Ausblick - Animation

<xsl:variable name="yoff">
<xsl:value-of select="50 + (position() * 20)"/>
</xsl:variable>
<switch>
<text systemLanguage="de"
style="fill: #cccccc; font-family:
sans-serif; font-size: 12pt;">
<tspan x="10" y="{$yoff}">
<xsl:apply-templates select="day"/>
<xsl:text>/</xsl:text>
<xsl:apply-templates select="month"/>
</tspan>
<tspan x="80" y="{$yoff}">
<tspan style="font-size: 11pt">
<xsl:if test="@status != ''">
<xsl:text>[</xsl:text>
<xsl:value-of select="@status"/>
<xsl:text>] </xsl:text>
<set>
<xsl:attribute name="xlink:href">
<xsl:text>#</xsl:text>
<xsl:value-of select="@status"/>
</xsl:attribute>
<xsl:attribute name="begin">mouseover</xsl:attribute>
<xsl:attribute name="end">mouseout</xsl:attribute>
<xsl:attribute name="to">visible</xsl:attribute>
</set>
</xsl:if>
</tspan>
<xsl:apply-templates select="what[@lang='de']"/>
</tspan>
</text>
<!-- Alternative folgt... -->
</switch>

Geschachtelte svg-Elemente, die die Seite wie Frames aufteilen; erkennbar an den unterschiedlichen Farben (Abb. 5)

Mehrere svg-Elemente zu verwenden, erleichtert es, Anwendungen zu strukturieren. Das in allen Fällen das gesamte svg-Element ausfüllende Rechteck sorgt für den Hintergrund, denn ein Attribut wie bgcolor oder background kennt SVG nicht.

Im insgesamt dritten (dem zweiten inneren) svg in Listing 7 finden sich zwei Texte, die identisch positioniert sind. Das rot hervorgehobene Attribut systemLanguage sorgt innerhalb des switch-Statements dafür, dass nur einer der beiden Texte dargestellt wird - abhängig davon, welche Sprache im Browser eingestellt ist, zeigt er den deutschen oder englischen Text. Beim zweiten wäre systemLanguage nicht unbedingt nötig. Fehlt das Attribut, gibt der Browser den Text als Default aus, immer wenn die Sprache nicht auf de gesetzt ist. Nachteil dieses Vorgehens: Nur Batik macht den Unterschied wirklich, das Adobe-Plug-in bleibt beim einmal gewählten Wert, gleich, wie die Sprachpräferenz sich ändern mag.

Auch bei der Verarbeitung der Ereignisse macht das Stylesheet diesen Sprachunterschied, der Script-Ausschnitt in Listing 8 ist lediglich etwas komplizierter. Zunächst berechnet das Script für jedes Ereignis ein Offset für den y-Wert. Abhängig davon, dass das Attribut status, das nur bei W3C-Veröffentlichungen vorkommt, nicht leer ist, stellt es vor den Text diesen Status in eckigen Klammern (siehe Abbildung 6) und - gibt mit dem Animationselement set einen Ausblick auf den zweiten Teil des Tutorials. Die Attribute zu set legen fest, dass beginnend bei einem mouseover und endend mit mouseout ein erklärender Text sichtbar wird - einer der am Schluss von Listing 7 unsichtbar erzeugten. Die Stileigenschaft visibility wechselt von hidden zu visible und zurück.

Innerhalb der text-Elemente erlauben tspans das genaue Platzieren der Teiltexte. (Mit einem Doppelklick ist der gesamte Text fürs Copy & Paste bereit.) Hier löst die Variable yoff die Platzierungsfrage, bei einfachen Texten hilft das Attribut dx oder dy:

<text x="80" y="80">
<tspan x="80" dy="12">...</tspan>
<tspan x="80" dy="12">...</tspan>
<tspan x="80" dy="12">...</tspan>
</text>

gibt die tspans immer mit x als 80 und y mit dem vorherigen Wert plus 12 wieder.

Für die Ereignisse, die ein nicht leeres Attribut url besitzen, erzeugt Listing 9 ein a-Element mit einem kleinen Rechteck und einem per path gezeichneten Dreieck darin, die auf Mausklick zu einer anderen Webseite weiterleiten - dem Inhalt des Attributs url.

Für SVG-fähige Browser geht es hier zur SVG-Ansicht (2002.svg).

Mehr Infos

Listing 9: Link erzeugen

<!-- variable: yoff s. Lst. 8, ynowoff = yoff - 10,
ynowoff1 = yoff - 8, y1off = ynowoff + 5,
y2off = ynowoff + 8 -->
<xsl:if test="@url != ''">
<a>
<xsl:attribute name="xlink:href">
<xsl:value-of select="@url"/>
</xsl:attribute>
<rect x="65" y="{$ynowoff}" width="10" height="10"
style="fill: #ccccff; stroke: none;"/>
<path d="M68,{$ynowoff1}L73,{$y1off}L68,{$y2off}z"
style="fill: #006699; stroke: none;"/>
</a>
</xsl:if>

Es ist leicht zu erkennen, dass zwei Versionen (Englisch und Deutsch) vorhanden sind, aber die Jahreszahl nicht präzise an derselben Stelle steht (Abb. 6 und 7).

Ein kleines Caveat: Beim Vergleich der Abbildungen 6 und 7 zeigt sich, dass zwar beide Sprachen ausgegeben werden, aber die Jahreszahl leider nicht 100%ig an derselben Stelle steht. Der Grund ist, dass auf unterschiedlichen Systemen jeweils andere Schrifttypen vorhanden sind, und eine Vorgabe font-family: sans-serif bewirkt, dass hier Arial, dort Helvetica die Arbeit ‘erledigen’.

SVG kennt einen Ausweg, auf den hier nur als Ausblick hingewiesen sei: Fonts lassen sich in der Sprache nicht nur entwickeln, sondern auch einbinden. Und freundlicherweise haben die Batik-Entwickler gleich einen Konverter geschrieben, der aus Truetype SVG zaubert:

java -jar ~/batik-1.5/batik-ttf2svg.jar myfont.ttf > myfont.svg

Die Zeittafel-Anwendung findet sich unter www.heise.de/ix/raven/Web/xml/svg/tl/2002.svg - und erfordert das anfangs genannte Plug-in oder einen Viewer wie Batik für die Darstellung. Wie üblich sind die Listings, ausführlicher als hier, bei der Online-Version, zu haben.

Ohne Quellen kommt ein solches Turorial nie zu Stande. Ob Nachschlagen oder Stöbern in vorhandenem Code: Ideen können nicht schaden. Die Sammelbesprechung ‘Mehr KBytes’ (siehe S. 146 in iX 12/02) widmet sich einer Reihe von Büchern, die im Laufe des letzten Jahres erschienen sind. Im Netz findet, wer sucht, einiges an SVG-Anwendungen, teilweise ganze Websites. Der Kasten ‘Online-Ressourcen’ enthält zumindest drei davon.

Online-Ressourcen
W3C
SVG-Spezifikation www.w3.org/TR/SVG
SVG-Überblick www.w3.org/Graphics/SVG
Tools
Adobe-Plug-in www.adobe.com/svg/
Batik (Apache) xml.apache.org/batik/
Anwendungen
Iván Hermans Vortrag www.w3.org/2002/Talks/SVG-StAugustin-IH/
SVG-Website www.svgspider.com/
W3C-"Büro" www.w3.org/Consortium/Offices/Presentations/SVGSlides/XMLExample/Example/addresses.svg
Freie True-Type-Schrifttypen bei
Fontz.ch fontz.ch/
Martin F. Core www.core.nu/v6/fonts_nav.html
The Chank Company www.chank.com/freefonts.php
Mehr unter
iX-SVG www.heise.de/ix/raven/Web/xml/svg/
Zusätzliche Attribute
SVG verfügt über einige Attribute, die die CSS-Spezifikation für HTML nicht vorsieht; hier folgt eineAuswahl für Textelemente. Weitere Eigenschaften (Properties), die SVG kennt, sind unter anderem dieschriftbezogenen (von font-family bis font-weight). Eine Liste findet sich unter www.w3.org/TR/SVG/propidx.html . Zum Vergleich: Die Liste für CSS2 steht unter www.w3.org/TR/CSS2/propidx.html.
Attribute Werte Veränderung in
fill #aabbcc, #abc, rgb(xxx,xxx,xxx) Farbe
fill-opacity 0.0 ... 1 Deckungsgrad (1 = völlig deckend)
stroke #aabbcc, #abc, rgb(xxx,xxx,xxx) Farbe
stroke-opacity 0.0 ... 1 Deckungsgrad (1 = völlig deckend)
text-anchor start | middle | end Ausrichtung an vorgegebenem Wert
text-rendering auto | optimizeSpeed | optimizeLegibility |geometricPrecision Kantenabrundung
writing-mode r-tb | rl-tb | tb-rl | lr | rl |tb Schreibrichtung (rl = *von rechts nach links)

Download der Listing-Dateien

[1] Jürgen Krüger, Christian Märtin; Grafik; Dehnbare Formate; SVG und VML: XML-Alternativen für dynamische Webgrafiken; iX 11/2000, S. 148; www.heise.de/ix/artikel/2000/11/148/

[2] Andreas Neumann, Andréas M. Winter; Kartographie im Internet auf Vektorbasis, mit Hilfe von SVG; www.carto.net/papers/svg/index_d.html

[3] Henning Behme; XML-Programmierung; Mutabor; XSLT-Tutorial I: Grundlagen und erste Beispielanwendung; iX 1/2001, S. 167; www.heise.de/ix/artikel/2001/01/167/; Teil II und III sind in iX 2/2001 und 3/2001 erschienen.

[4] Henning Behme; XML-Programmierung; Wenn Markup lockt; WML: XML-Dat(ei)en aufs Handy bringen; iX 4/2000, S. 178; www.heise.de/ix/artikel/2000/04/178/

Dietmar Jokisch und Michael Riepe haben gute Ideen beigesteuert.

Mehr Infos

iX-TRACT

  • SVG, die skalierbare Vektorgrafik fürs Web, gilt vielen bereits als ernst zu nehmende Konkurrenz für Macromedias Flash.
  • Vorteile von SVG sind Herstellerunabhängigkeit sowie XML als Basis, weil Suchmaschinen die Textdateien durchforsten können.
  • Außer üblichen Zeichenmöglichkeiten inklusive Filtern und Beschneidungspfaden bietet SVG Animation und Scripting.
Mehr Infos

Tutorial-Inhalt

Teil I: Grundlegende SVG-Elemente, Struktur von Dokumenten, Stilangaben, Links, Erzeugung aus XML

Teil II: Verläufe, Filter, Beschneidungspfade, Masken, Animation

Teil III: Tabellen einer Datenbank über eine Skriptsprache grafisch darstellen

(hb)