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.
- Henning Behme
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.
YAXL: yet another XML language ...
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).
Webmaster-Aufgabe MIME-Typ
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.
Struktur und Elemente
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.
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).
d-Attribut: Pfadfinders Paradies
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).
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).
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) |
Mit Bézier in die Kurven
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).
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;"/>
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).
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;"/>
<!-- ... -->
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.
SVG in HTML und aus XML
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.
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.
Generierung von Dateien durch ein XSLT-Script
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).
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>
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'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>
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>
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.
Besonderheiten und Kleinigkeiten
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).
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>
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) |
Literatur
[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.
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.
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)