Frisch gestrichen

2D-Grafik ist mehr als Text und ein paar grafische Primitive. Elemente müssen sich durch Verläufe, Beschneidungspfade und Filter modifizieren lassen. SVG bietet all das - plus Animation.

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

Wer Software wie Photoshop, Gimp oder Illustrator kennt, erwartet von einer Grafiksprache fürs Web vielleicht zu viel. Immerhin beinhaltet die Scalable Vector Graphics (SVG) eine Reihe von Filtern für die Bearbeitung von Texten und Bildern. Außerdem ist in SVG ein Teil der Synchronized Multimedia Integration Language (SMIL) 2.0 einbezogen, wodurch sich SVG-Elemente animieren lassen.

Alles in SVG ist Text und Grafik zugleich. Text insofern, als die Dateien immer nur Text enthalten (bis auf referenzierte Bitmap-Grafiken). Grafik insofern, als Pfade, Rechtecke und Text immer grafische Elemente darstellen. Bevor es in diesem Teil des Tutorials um Aspekte wie Verläufe, Filter und Animation geht, hier deshalb ein letzter Exkurs in die Textwelt.

Neben den im ersten Tutorialteil vorkommenden üblichen Eigenschaften von Text - bis hin zum Rotieren et cetera - können Entwickler und Designer Zeichenketten außer auf die ‘normale’ Weise auch anders laufen lassen: etwa senkrecht wie auf Leuchtreklamen oder entlang einem vorgegebenen Pfad. Senkrechter Text erfordert im Stilattribut die Eigenschaften writing-mode mit dem Wert tb und glyph-orientation-vertical mit dem Wert 0.

Für SVG-fähige Browser geht es hier weiter: Text waagerecht, rotiert und senkrecht.

<text id="text03" x="150" y="70"
style="writing-mode: tb;
glyph-orientation-vertical: 0;
font-family: sans-serif;
font-size:10; fill: #339933;">
senkrechter Text
</text>

Text lässt sich allerdings nicht nur senkrecht, sondern entlang beliebiger Pfade schreiben. Listing 1, das Code aus der SVG-Spezifikation nutzt, schreibt eine Kurve und einen Text, der durch das Element textPath den vorher definierten Pfad referenziert.

Mehr Infos

Listing 1: Text mit Pfadangabe

<defs>
<path id="pathfortext"
d="M 100 200
C 200 100 300 0 400 100
C 500 200 600 300 700 300"
fill="none" stroke="#666666"/>
</defs>
<use xlink:href="#pathfortext" fill="none" stroke="none"/>
<text font-family="sans-serif" font-size="24" fill="#666699" >
<textPath xlink:href="#pathfortext" startOffset="10">
When I think of all the
<tspan fill="#669966">good</tspan>
<tspan fill="#666699">times that&apos;s
been wasted having good times...</tspan>
</textPath>
</text>

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

Mit textPath - in Grau zu sehen - ist der Weg definiert, an dem sich der Text orientiert (Abb. 1).

Zu Texten kommt dieser Artikel zurück, wenn es darum geht, sie zu animieren. Zunächst seien ein paar Aspekte von SVG in den Vordergrund gerückt, die offensichtlich grafischer Natur sind.

Ob Root-Element, Text oder Grafik: Sie lassen sich alle durch andere Elemente beeinflussen. Verläufe und Beschneidungspfade färben sie ein oder zeigen nur einen Teil des Ganzen. Im einfachen Fall handelt es sich um einen Verlauf (engl.: gradient), der einen farblichen Übergang zwischen zwei oder mehr Farben beschreibt.

Listing 2 zeigt vier Verläufe. Das erste der inneren svg-Elemente enthält zunächst ein Rechteck, das den gesamten Bereich ausfüllt, einen linearGradient, der durch x1="0%" x2="100%" y1="0%" y2="100%" von oben links nach unten rechts verläuft und sich von einem hellen zu einem dunklen Blauton verändert. Das obere Rechteck referenziert mit fill: url(#zweiF) ebenfalls einen linearen Verlauf, der von links nach rechts die Farbe ändert.

Mehr Infos

Listing 2: Verläufe

<svg ...>
<defs>
<linearGradient id="zweiF">
<stop offset="0%" style="stop-color: #ff0000;"/>
<stop offset="100%" style="stop-color: #00ffff;"/>
</linearGradient>

<linearGradient id="schraeg"
x1="0%" x2="100%" y1="0%" y2="100%">
<stop offset="0%" style="stop-color: #9999ff;"/>
<stop offset="100%" style="stop-color: #000066;"/>
</linearGradient>

<radialGradient id="rund1" cx="200" cy="150"
r="200" fx="200" fy="150"
gradientUnits="userSpaceOnUse">
<stop offset="0%" style="stop-color: #9999ff;"/>
<stop offset="50%" style="stop-color: #ff9999;"/>
<stop offset="100%" style="stop-color: #99ff99;"/>
</radialGradient>

</defs>

<svg x="10%" y="10%" width="80%" height="80%">
<rect width="100%" height="100%"
style="fill: url(#schraeg); stroke: #333333;"/>

<rect x="20" y="20" width="400" height="100"
style="fill: url(#zweiF); stroke: #333333;"/>

<svg x="20" y="130" width="400" height="300">
<rect x="0" y="0" width="400" height="300"
style="fill: url(#rund1); stroke: #333333;"/>
</svg>

<text x="430" y="60"
style="fill: url(#zweiF); stroke: #666666;
font-family: sans-serif; font-size: 24pt">
Aaaah
</text>
</svg>
</svg>

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

Lineare und kreisförmige Verläufe in Objekten und Text können manches verschönern (Abb. 2).

Im unteren Rechteck in Abbildung 2 ist ein runder Verlauf (radialGradient) zu sehen, während die Zeichenkette oben rechts, der das Stilattribut den Verlauf als Füllfarbe zuweist (fill: url(#zweiF)), wiederum den schrägen Verlauf beinhaltet. Immer zu beachten: Den Listings fehlt der ‘Kopf’, um eine vollständige SVG-Datei zu sein (siehe Teil I des Tutorials).

Außer Verläufen lässt sich anderes Material in Objekten referenzieren oder als Hintergrund verwenden. Hierzu dienen Beschneidungspfade (engl.: clipping path) und Masken. Wie Verläufe stehen auch Clipping paths, die hier solcherlei Maskierung repräsentieren sollen, innerhalb des Definitionsteils von SVG-Dokumenten. Listing 3 zeigt einen Beschneidungspfad, der aus einem Kürzesttext besteht (‘iX’), allerdings in großer Schrift, den wiederum ein Element als clip-path referenzieren muss (zu beachten: die unterschiedliche Schreibweise in Definition und ‘Aufruf’).

Mehr Infos

Listing 3: Beschneidungspfad

<svg ...>
<defs>
<clipPath id="mytext">
<text x="180" y="400" style="font-family: sans-serif;
font-size: 260pt; font-weight: bold;
fill: none;">iX
</text>
</clipPath>
</defs>

<svg x="10%" y="10%" width="80%" height="80%" clip-path="url(#mytext)">
<image xlink:href="caravaggio.emmaus.jpg" width="389" height="537"
x="0" y="0"/>
</svg>
</svg>

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

Hinter dem ‘iX’ als Beschneidungspfad liegt ein Gemälde, das hier kaum noch zu sehen ist (Abb. 3).

Ob Kreise, Rechtecke oder beliebige Pfade: alles kann dazu dienen, Ausschnitte aus Objekten darzustellen. Wie weiter unten zu lesen ist, kann man Beschneidungspfade durchaus verändern (animieren).

Ein wichtiges - und umfangreiches - Kapitel der SVG-Spezifikation ist das der Filter. Hier ist es nur ansatzweise möglich, zu beschreiben, wie man sie nutzen kann. Wer sich intensiv mit ihnen beschäftigen will, findet in der Literatur (siehe [2]) einige Bände, die dazu ausreichend viel zu bieten haben; die Spezifikation nicht zu vergessen. Welche Filter zur Verfügung stehen, ist dem Kasten ‘Filterelemente’ zu entnehmen.

FilterElemente
Filter Wirkung
feBlend erzeugt aus zwei durch Attribute übergebenen Bildern eins
feColorMatrix transformiert über eine Matrix die Rot-, Grün, Blau- und Alpha-Werte eines Bildes
feComponentTransfer verändert Helligkeit, Kontrast oder Farben
feComposite führt Operationen auf zwei über Attribute übergebenen Bildern aus
feConvolveMatrix verzerrt die Eingabe (beispielsweise Embossing) durch Kombination benachbarter Pixelwerte
feDiffuseLighting erzeugt den Effekt einer weit entfernten Lichtquelle
feDisplacementMap entfernt ein Bild von einem zweiten
feFlood erzeugt den Effekt eines auf ein Objekt fallenden Lichts
feGaussianBlur lässt ein Bild verschwimmen
feImage referenziert ein externes Bild (auch Bitmap) für die Erzeugung von Filtern
feMerge erzeugt die Ausgabe aus mehreren Schichten (layers), Ergebnisse von Filtern
feMorphology verdickt oder verdünnt die Eingabe
feOffset verschiebt die Eingabe
feSpecularLighting beleuchtet ein Bild über dessen Alpha-Kanal
feTile füllt eine Fläche mit Kacheln
feTurbulence erzeugt einen Wolken- oder Marmoreffekt

Gimp- und Photoshop-Anwendern muss niemand sagen, was Filter sind. Hier eine Andeutung. Einem grafischen Objekt oder seinem Alpha-Kanal (dem außer Rot, Grün und Blau vierten Farbkanal, der die Transparenz definiert) verschaffen Filter Modifikationen recht unterschiedlicher Art. Sie sind einzeln und in Verkettung nutzbar. Ein weit verbreiteter dürfte der in jedem Buch vorkommende Drop Shadow sein (kommt gleich :-). Er bewirkt einen leichten 3D-Effekt durch den Schatten neben dem eigentlichen Objekt.

Für SVG-fähige Browser geht es hier zur SVG-Ansicht (möglicherweise nicht mit dem Adobe-Plugin unter Linux; dann Mozilla neu starten ;-).

iX hat einen Schatten, erzielt durch drei Filter (Abb. 4).

Wie Verläufe et cetera platzieren Entwickler Filter im Definitionsteil, damit sie nicht dargestellt werden.

<filter id=’myFilter’> ...
</filter>

muss eine ID haben, damit er referenzierbar ist. Welche Filter zum Tragen kommen, hängt vom Einzelfall ab. Wichtig ist zu entscheiden, ob sie sich auf die Grafik selbst oder deren Alpha-Kanal beziehen. In Listing 4 sind drei Filter im Einsatz. feGaussianBlur nutzt mit SourceAlpha den Alpha-Kanal und erzeugt Verschwommenes in der Variablen blur. feOffset nimmt das verschwommene Resultat im Attribut in auf, verschiebt es durch die Attribute dx und dy; das Ergebnis liegt in offsetBlur. feMerge schließlich fasst alle drei zusammen. Erst danach kommt es zum Rendering.

Mehr Infos

Listing 4: Filter

  <defs>
<filter id="iXfilter">
<feGaussianBlur in="SourceAlpha" stdDeviation="2"
result="blur"/>
<feOffset in="blur" dx="6" dy="6"
result="offsetBlur"/>
<feMerge>
<feMergeNode in="offsetBlur"/>
<feMergeNode in="blur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>

<g>
<image xlink:href="ix-symbol.svg"
x="20" y="20" width="171.5"
height="181.5"
filter="url(#iXfilter)"/>
</g>

Um eine Weile beim iX-Logo zu bleiben: Filter können unter anderem dazu dienen, Effekte zu erzielen, für die man ohne sie viele Pfade benötigte. Im ersten Teil des Tutorials war die Rede vom aus dem Illustrator exportierten iX-Logo, das durch ein Symbol, wie es der Anfang von Listing 5 wiedergibt, deutlich einfacher zu gestalten ist.

Mehr Infos

Listing 5: Filter statt Pfade

  <defs>
<symbol id="ixlogo">
<path d="M120.966,24.299H89.318l14.368,49.51l-
69.509,101.74h31.648l47.763-69.315l10.096,35.92h31.648l-19.804-68.15l33.978-
49.705h-31.842L125.82,41.58L120.966,24.299z"/>
<path d="M56.312,68.179h31.648l-50.287,73.586H6L56.312,68.179z"/>
<path d="M84.066,49.256c-2.505,0.969-5.228,1.501-8.075,1.501c-12.359,0-
22.378-10.019-22.378-
22.378S63.632,6,75.992,6c5.948,0,11.354,2.321,15.361,6.105"/>
</symbol>

<filter id="iXfilter" filterUnits="userSpaceOnUse"
x="0" y="0" width="175.5" height="181.5">
<feGaussianBlur in="SourceAlpha" stdDeviation="4" result="blur"/>
<feOffset in="blur" dx="4" dy="4" result="offsetBlur"/>
<feSpecularLighting in="blur" surfaceScale="4" specularConstant="1"
specularExponent="10" lighting-color="white"
result="specOut">
<fePointLight x="-5000" y="-10000" z="20000"/>
</feSpecularLighting>
<feComposite in="specOut" in2="SourceAlpha"
operator="in" result="specOut"/>
<feComposite in="SourceGraphic"
in2="specOut" operator="arithmetic"
k1="0" k2="1" k3="1" k4="0" result="litPaint"/>

<feMerge>
<feMergeNode in="SourceAlpha"/>
<feMergeNode in="litPaint"/>
</feMerge>
</filter>
</defs>

<rect width="100%" height="100%"
style="fill: #000000;"/>

<g transform="translate(100,50)" filter="url(#iXfilter)"
style="fill: none; stroke-linecap: round; stroke-linejoin: round;">
<use xlink:href="#ixlogo" style="stroke: #0c419a ; stroke-width: 12;"/>
</g>

<g transform="translate(300,50)"
style="fill: none; stroke-linecap: round; stroke-linejoin: round;">
<use xlink:href="#ixlogo" style="stroke: #0c419a ; stroke-width: 12;"/>
<use xlink:href="#ixlogo" style="stroke: #1151a1; stroke-width: 11.5;"/>
<!-- ... -->
<use xlink:href="#ixlogo" style="stroke: #ffffff; stroke-width: 0.7;"/>
</g>

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

Zwei Logos: das linke kreieren Filter, das rechte Pfade (Abb. 5).

Der der Spezifikation entnommene und veränderte Filter reicht fast an die Pfadversion heran und ließe sich sicherlich noch weiter an ihn annähern. Hinzugekommen im Vergleich zum Listing 4 sind feSpecularLight sowie feComposite (zweimal). Daran lässt sich erkennen, dass eine Vielzahl an Filterungsvarianten vor den Entwicklern steht. Am Ausprobieren dürfte kaum jemand vorbeikommen.

Es kann nicht oft genug gesagt und geschrieben werden: Animationen sollte man so sparsam wie es nur geht verwenden: weder die Seiten überfrachten noch die Besucher strapazieren. Genau diese Maxime verletzt dieser Artikel zwangsläufig, weil er gerade die grafischen Eigenschaften vorstellt.

Animationen hat das W3C nicht erst für SVG spezifiziert. Dafür gibt es schließlich SMIL, die Synchronized Multimedia Integration Language, die das Konsortium im August vorigen Jahres in der Version 2.0 freigegeben hat (siehe [1]); im September außerdem die SMIL-Animationen, die das ebenfalls im September verabschiedete SVG wiederum für die ‘eigenen’ Animationen nutzt.

Leider kommen Animationen in Zeitschriften nicht gut, weswegen die Screenshots nur einen Teil dessen wiedergeben können, was SVG leistet. Online kann die ganze Pracht der Animationen zu sehen sein. Um das iX-Logo noch einmal zu strapazieren: Es lässt sich drehen, verkleinern und in alle Richtung bewegen. Verantwortlich dafür sind die aus SMIL übernommenen Elemente, die der Kasten ‘Animationselemente’ aufführt.

Animationselemente
Element Wirkung
animate verändert ein Attribut im Laufe der Zeit (cx, opacity ...)
set setzt den Wert eines Attributs für eine bestimmte Zeit(beispielsweise der Rollover-Effekt)
animateColor verändert die Farbe im Laufe der Zeit
animateMotion lässt ein referenziertes Element sich an einem Pfad bewegen
animateTransform verändert ein Attribut im Laufe der Zeit (scale, rotate, skewX ...)

Mit ihrer Hilfe können Entwickler Teile von SVG-Dokumenten in Bewegung bringen. Listing 6 beinhaltet im Element animate, dass die per g zusammengefasste Gruppe, die außer der Animation nur das iX-Logo enthält, schrumpft, wächst und auf Normalmaß zurückschrumpft. Das Attribut attributeName legt fest, auf welche Eigenschaft sich die Animation beziehen soll; hier ist es scale. begin definiert den Anfangszeitpunkt, form und to legen Anfangs- und Endwerte fest, und dur schließlich besagt, wie lange die Animation dauern soll. Hier ist für die einzelnen Animationen vorgeschrieben, wann genau sie zu starten haben.

Mehr Infos

Listing 6: iX-Logo kleiner und größer

<g>
<use xlink:href="#ixlogo"/>
<animateTransform attributeName="transform" attributeType="XML"
type="scale" begin="2s" from="1" to="0.5" dur="2s"/>
<animateTransform attributeName="transform" attributeType="XML"
type="scale" begin="4s" from="0.5" to="1.5" dur="2s"/>
<animateTransform attributeName="transform" attributeType="XML"
type="scale" begin="6s" from="1.5" to="1.0" dur="2s"/>
</g>

Man kann sie stattdessen direkt nacheinander schalten (siehe weiter unten). Statt scale zu verändern, kann eins der anderen Attribute von Objekten einer Animation unterzogen werden. translate würde beispielsweise die Positionierung auf dem Bildschirm variieren, also das Element verschieben. rotate brächte das Element dazu, sich um sich selbst oder etwas anderes zu drehen - je nach Ursprungskoordinaten.

Denkbar sind unterschiedliche Geschwindigkeiten, mit denen sich bewegte Objekte durch weitere Attribute erreichen lassen. Iván Herman hatte in seinem Vortrag in Sankt Augustin (Achtung: Verweis auf SVG :-) einen Slide, aus dem hier eine Winzigkeit verwendet sei. Ein Kreis und ein Rechteck bewegen sich dieselbe Strecke von links nach rechts - aber mit unterschiedlichem Tempo. Das regeln die Attribute keyTimes, keySplines und calcMode. keyTimes bestimmt gemeinsam mit values die Zeitpunkte, zu denen die Animation läuft. calcMode="spline" zieht gleichsam eine Bézierkurve von einem values-Wert zum anderen; die Werte der Bézierkurve wiederum regelt das Attribut keySplines. Das letzte Attribut in Listing 7 definiert schlicht, ob die Ereignisse wiederholt stattfinden sollen, was hier der Fall sein soll (durch repeatCount="indefinite").

Mehr Infos

Listing 7: Bewegungen

  <circle id="circle" cx="30" cy="90" r="10" 
style="fill: #669966">
<animate attributeName="cx"
values="30;600" keyTimes="0;1"
keySplines="0 0 1 1" begin="1s"
calcMode="spline" dur="5s" repeatCount="indefinite"/>
</circle>

<rect id="rect" x="20" y="120" width="20"
height="20" style="fill: #666699">
<animate attributeName="x"
values="20;600" keyTimes="0;1"
keySplines=".5 0 .5 1" begin="1s"
calcMode="spline" dur="5s" repeatCount="indefinite"/>
</rect>

Ästhetik beschränkt sich nicht auf Bilder. Wie viele gute Bücher (oft von kleinen Pressen kommend) beweisen, beeinflusst der Satz die Rezeption erheblich. Da liegt es nahe, SVG für die Präsentation kurzer Texte einzusetzen. Hier seien zwei Gedichte verwendet, die auf unterschiedliche Weise zeigen, wie SVG die Darstellung lenken kann.

Zunächst das ‘Drumherum’: Am linken Rand von Abbildung 6 stehen die anklickbaren Namen zweier Autoren, deren Gedichte auf zwei SVG-Seiten erscheinen. Zu Beginn sind die Zeichenketten nicht sichtbar, weil das darunter liegende Rechteck dieselbe Füllfarbe hat wie der Text. Erst mit der für rect definierten Animation, die den Deckungsgrad des Rechteck-Graus verringert, wächst die Lesbarkeit der Namen:

<animate id="transpar1" 
attributeName="fill-opacity" begin="1s"
from="1" to=".5" dur="3s" fill="freeze"/>

Verändern soll die Animation das Attribut fill-opacity - von 100%iger Deckung (from) zu 50%iger (to). Sie soll drei Sekunden benötigen (dur) und den Endzustand beibehalten (freeze als Wert von fill). Anmerkung: Das Attribut fill in Animationselementen hat nichts mit dem Stilattribut der Füllfarbe anderer Elemente gemein. Das Attribut id erlaubt es anderen Elementen, diese Animation zu referenzieren, was die folgenden umsetzen.

Vorsicht ist geboten, wenn mehrere Elemente übereinander liegen. Wegen des so genannten Painter’s Model - wie bei Ölbildern überdeckt das später Gemalte das frühere - wechselt ein Viewer nicht den Cursor, wenn die Maus sich über einem Link befindet, der unter einem Rechteck liegt. Links gehören deshalb definitiv nach oben.

Über und unter dem Quasi-Menü sind zwei Linien zu erkennen, die nach der Veränderung des Rechtecks beginnen, sich zu bewegen. Eine dritte Linie wandert von oben in Sichtweite und unten aus ihr heraus. Die drei Linien richten sich nach dem Rechteck, denn für sie ist als Anfang der Animation ein Zeitwert vorgegeben: transpar1.end+1s heißt, dass sie eine Sekunde nach dem Ende derjenigen mit der ID transpar1 loslegen sollen. Für die senkrecht laufende Linie sind zwei Animationen festzulegen, denn die Werte für y1 und y2 müssen sich beide ändern, damit sie als Ganzes wandert:

<animate attributeName="y1"
begin="transpar1.end+1s"
from="-450" to="1000" dur="4s" fill="freeze"/>
<animate attributeName="y2"
begin="transpar1.end+1s"
from="-200" to="1300" dur="4s" fill="freeze"/>

Wer ein Riesendisplay voraussetzt, muss eventuell die Werte 1000 und 1300 höher setzen, damit die Linie tatsächlich verschwindet.

Erst nach all diesen Bewegungen erscheint allmählich der Text des berühmten ‘Herbsttag’, indem die fill-opacity von 0 bis 1 wächst. Im Listing 8 ist die Zeitangabe am Listingende absolut (begin="8s"). Sie lässt sich wie bei Rechteck und Linien an eine andere koppeln, wie ein zweites, weniger bekanntes Gedicht zeigt: E. E. Cummings’ ‘l(a’, das nicht insgesamt seinen Deckungsgrad verändert, sondern Zeile für Zeile. Listing 9 enthält ein Fragment, das für jedes tspan eine Animation enthält. Sie alle sind voneinander abhängig, weil sie sich auf die jeweils vorherige beziehen: von ihr ihren Anfang herleiten:

<animate id="line1" 
attributeName="fill-opacity"
begin="line0.begin+1s"
from="0" to="1" dur="2s" fill="freeze"/>
Mehr Infos

Listing 8: Textveränderungen

<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: #003300; stroke: none;"/>

<rect x="10" y="100" width="100" height="400"
style="fill: #cccccc; fill-opacity: 1;">
<animate id="transpar1"
attributeName="fill-opacity" begin="1s"
from="1" to=".5" dur="3s" fill="freeze"/>
</rect>

<text style="font-family: sans-serif; font-size: 10pt;
fill: #cccccc; fill-opacity: 1;">
<tspan x="15" y="122">
<a xlink:href="cummings.svg">e. e. cummings</a>
</tspan>
<tspan x="15" dy="12">r. m. rilke</tspan>
</text>

<line x1="10" y1="97" x2="600" y2="97"
style="stroke: #cccccc; stroke-width: .7;">
<animate attributeName="x2" begin="transpar1.end+1s"
from="600" to="110" dur="2s" fill="freeze"/>
</line>

<line x1="10" y1="503" x2="110" y2="503"
style="stroke: #cccccc; stroke-width: .7;">
<animate attributeName="x2" begin="transpar1.end+1s"
from="110" to="600" dur="2s" fill="freeze"/>
</line>

<line x1="450" y1="-450" x2="450" y2="-50"
style="stroke: #cccccc; stroke-width: .7;">
<animate attributeName="y1" begin="transpar1.end+1s"
from="-450" to="1000" dur="4s" fill="freeze"/>
<animate attributeName="y2" begin="transpar1.end+1s"
from="-200" to="1300" dur="4s" fill="freeze"/>
</line>

<text id="herbsttag" style="font-family: sans-serif;
font-size: 12pt; font-weight: bold;
fill: #ccffcc; fill-opacity: 0;">
<tspan x="200" y="176"
style="fill: #cccccc;">rainer maria rilke
(1875-1926)</tspan>

<tspan x="200" y="200"
style="font-size: 18pt;
font-weight: bold;">Herbsttag</tspan>

<tspan x="200" dy="28">Herr: es ist Zeit. Der
Sommer war sehr groß.</tspan>

<!-- die weiteren Zeilen -->

<animate attributeName="fill-opacity" begin="8s"
from="0" to="1" dur="5s" fill="freeze"/>

</text>

</svg>
Mehr Infos

Listing 9: Zeilenweise animieren

  <text id="cummingsla" style="font-family: sans-serif;
font-size: 12pt; font-weight: bold;
fill: #cccccc; fill-opacity: 1;">
<tspan x="300" y="200"
style="fill-opacity: 0;">
e. e. cummings (1894-1962)
<animate attributeName="fill-opacity" begin="8s"
from="0" to="1" dur="2s" fill="freeze"/>
</tspan>

<tspan x="300" dy="28"
style="font-size: 18pt; font-weight: bold;
fill: #669966; fill-opacity: 0;">l(a
<animate id="title" attributeName="fill-opacity"
begin="9s" from="0" to="1" dur="2s"
fill="freeze"/>
</tspan>

<tspan x="300" dy="56"
style="fill-opacity: 0;">l(a
<animate id="line0" attributeName="fill-opacity"
begin="title.end+1s"
from="0" to="1" dur="2s" fill="freeze"/>
</tspan>

<!-- weitere tspan-Elemente -->
</text>

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

Die Menüzeilen kommen erst zum ‘Vorschein’, wenn die Transparenz des Rechtecks gleicher Farbe zunimmt, und der Text erscheint erst nach dem Ende der ersten Animation (Abb. 6 und 7).

Die Abbildungen 6 und 7 zeigen zwei Stadien der Wiedergabe.

Um wie angekündigt, auf Textanimation entlang eines Pfades zurückzukommen, ist Listing 1 lediglich um eine Animation innerhalb des Textelementes, wie es Listing 10 zeigt, zu ergänzen. Der Effekt: text wandert von rechts nach links entlang der Welle.

Mehr Infos

Listing 10: Text am Pfad

<text font-family="sans-serif"
font-size="24" fill="#666699" >
<textPath xlink:href="#pathfortext" startOffset="10">
When I think of all the
<tspan fill="#669966">good</tspan>
<tspan fill="#666699">times that&apos;s
been wasted having good times...</tspan>

<animate attributeName="startOffset" begin="1s"
from="200" to="10" dur="3s" fill="freeze"/>
</textPath>
</text>

Auf die Dauer ist die Animation von Texten vielleicht etwas langweilig, und für Präsentationen sind Grafiken eh unabdingbar. Deshalb soll hier ein klassisches Bild für ein paar weiter reichende Effekte dienen: Jan van Eycks Arnolfini-Hochzeit. Im ersten Schritt begrenzt ein clipPath den darzustellenden Ausschnitt eines svg-Elements:

<defs>
<clipPath id="roundit">
<circle cx="397" cy="180" r="33"/>
</clipPath>
</defs><- ... ->
<svg ... clip-path="url(#roundit);"><- ... ->
</svg>

Alles was innerhalb des Kreises liegt, ist sichtbar, alles andere nicht, weil das gesamte SVG-Dokument den clipPath erhalten hat.

Da das van-Eyck-Bild ein berühmtes Detail, den Spiegel in der Mitte, enthält, ist der clipPath genau auf ihn ausgerichtet. Listing 11 bewirkt, dass der clipPath sich verändert, indem dem in ihm enthaltenen circle eine Animation beigegeben ist. Sie muss Bestandteil des Kreises, nicht des Pfades sei.

Mehr Infos

Listing 11: Animierter clipPath

  <defs>
<clipPath id="roundit">
<circle cx="397" cy="180" r="33">
<animate id="bigger" attributeName="r" begin="2s"
from="33" to="440" dur="5s" fill="freeze"/>
</circle>
</clipPath>
</defs>

<rect width="100%" height="100%"
style="fill: #000000;"/>

<svg width="100%" height="100%"
clip-path="url(#roundit);">
<rect width="100%" height="100%"
style="fill: #000000;"/>

<text style="font-family: serif; font-size: 10pt;
font-weight: normal; fill: #ccffcc;
fill-opacity: 0;">
<tspan x="20" y="50">
Jan van Eyck [~1390-1441]</tspan>
<tspan x="20" dy="15" style="fill: #669966;">
Arnolfini-Hochzeit (1434)</tspan>
<tspan x="20" dy="15">Öl auf Holz, 82x60 cm</tspan>
<animate attributeName="fill-opacity"
begin="bigger.end"
from="0" to="1" dur="5s" fill="freeze"/>
</text>

<image xlink:href="arnolfini.jpg"
width="389" height="537"
x="200" y="20"/>
</svg>

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

Animierter clipPath: Im einen Bild öffnet sich der Kreis allmählich, im anderen ist diese Animation beendet und die textbezogene (links oben) läuft (Abb. 8 und 9).

Nach zwei Sekunden startet die Animation und eröffnet dem Surfer nach und nach das gesamte Bild (siehe zwei Stadien in Abb. 8 und 9). Erst wenn der Vorgang abgeschlossen ist, fängt die zweite in Listing 11 enthaltene Animation an: das langsame Erscheinen des Begleittextes. Dies erreicht man durch die Referenz auf die ID der vorausgehenden Animation; begin="bigger.end" verweist auf die vorher definierte Animation (id="bigger") und legt nach deren Ende los.

Wenn ein clipPath animierbar ist, sollte dasselbe für Filter gelten. Die Arnolfini-Hochzeit und der clipPath seien noch einmal bemüht. Der clipPath soll sich über einem unscharfen Bild bewegen, das erst scharf wird, wenn die Bewegung abgeschlossen ist.

Listing 12 bezieht die Animationen auf den clipPath und auf das Bild, dessen Ausschnitt zu sehen ist. Diese Konzentration von Bewegtheit führt allerdings dazu, dass die Animationen nicht rund laufen, sondern rucklig. Womit der Kreis sich schließt: Weniger kann mehr sein ...

Mehr Infos

Listing 12: Animierter Filter

  <defs>
<clipPath id="roundit">
<circle cx="160" cy="180" r="133"/>
</clipPath>
<filter id="myGauss">
<feGaussianBlur in="SourceGraphic" stdDeviation="0">
<animate attributeName="stdDeviation"
begin="0s" from="0"
to="4" dur="1" fill="freeze"/>
<animate attributeName="stdDeviation"
begin="10s" from="4"
to="0" dur="1" fill="freeze"/>
</feGaussianBlur>
</filter>
</defs>

<svg width="100%" height="100%"
clip-path="url(#roundit)">
<rect width="100%" height="100%"
style="fill: #000000;"/>
<image xlink:href="arnolfini.jpg"
width="389" height="537"
x="50" y="20" filter="url(#myGauss)">
<animate id="aright" attributeName="x"
begin="3s" from="50"
to="-120" dur="2"/>
<animate id="aleft" attributeName="x"
begin="aright.end" from="-120"
to="10" dur="3"/>
<animate attributeName="x"
begin="aleft.end" from="10"
to="-40" dur="3" fill="freeze"/>
</image>
</svg>

[1] Susanne Boll, Horst Eidenberger; Web-Standards; Medienmix; SMIL 2.0: Markup-Sprache für Multimedia-Präsentationen; iX 11/2002, S. 113

[2] Henning Behme; Buchmarkt; Mehr KBytes; SVG; iX 12/2002, S. 146

Mehr Infos

iX-TRACT

  • Die vom W3C definierte 2D-Grafiksprache SVG erlaubt Entwicklern, in reinem XML-Text Konstrukte wie Verläufe, Beschneidungspfade und Filter zu beschreiben.
  • Aus der Synchronized Multimedia Integration Language, ebenfalls eine W3C-Spezifikation, haben die Autoren für SVG Animationen abgeleitet.
  • Außer Textelementen und Bitmapgrafiken lassen sich Beschneidungspfade und Filter für Animationen nutzen.
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

Download der Listing-Dateien (hb)