CSS, HTML und Javascript mit {stil}

SVG Animate

SVG SMIL Animation ohne Javascript und CSS

SVG kann mit Javascript und CSS animiert werden, hatte aber auch ein eigenes Animationsmodell: SMIL – Synchronized Multimedia Integration Language.

Als zu komplex und zu fehlerlastig können wir SMIL als ad acta legen – spätestens, seitdem Chrome SMIL abgestellt hat.

Alternativen sind CSS und Javascript, Velocity.js, motionPath, Libraries wie GreenSocks und snap.svg

SVG ist ein spezielles DOM-Element mit einer ähnlichen Syntax wie HTML: SVG-Elemente bestehen aus Tags, Attributen und Verhalten. Sie können mit CSS animiert werden – wenn auch mit Einschränkungen.

CSS transitionAlle style-AttributeNicht bei SVG in img-Tag
CSS transformAlle style-AttributeNicht bei SVG in img-Tag
CSS keyframeAlle style-AttributeNicht bei SVG in img-Tag
CSS und JavascriptAlle style- und Geometrie-AttributeNicht bei SVG in img-Tag

SVG mit CSS animieren

SVG unterstützt CSS und kann im style-Attribut dekorative Eigenschaften wie fill, opacity, stroke, stroke-width und font-family zusammenfassen.

Diese Eigenschaften können entweder als fill="#fff" oder style="fill:#fff" geschrieben werden und lassen sich mit CSS animieren.

SVG-Geometrie-Attribute wie x, y, width, height, r, rx, ry bleiben allerdings außen vor – sie lassen sich nicht im style-Attribut zusammenfassen und nicht mit CSS animieren (kommt erst mit SVG2).

Einfache CSS-Animationen mit transition funktionieren wie bei HTML-Elementen.

<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 299.5 299.5">
<style>
.f1 { fill: blue; transition: fill 1s;}
.f1:hover { fill: green; }
</style>
  <path style="fill:#aaa" d="m 220,67.51 c -23,0 -42,16.78 -50,40.59 l 22,0 c 5,-11.31 15,-18.51 26,-18.51 c 18,0 32,19.91 32,44.51 l 0,17.3 l -217,0 c -9,0 -15,6.9 -15,15.7 l 0,1.3 c 0,8.7 6,15.7 15,15.7 l 6,0 c 2,27.6 17,50.9 38,63.5 l -3,15.1 c -3,6.3 2,12.8 7,14.4 c 6,1.8 12,-1.9 15,-8.4 l 4,-12.6 c 3,0.9 8,1.4 13,1.4 l 81,0 c 6,0 11,-0.6 14,-1.8 l 5,13.1 c 2,6.5 8,10.2 14,8.6 c 7,-1.9 10,-8.2 9,-14.6 l -5,-16.3 c 17,-10.2 28,-26.9 34,-46.7 l 0,-0.1 c 5,-10.1 8,-22.1 8,-34.8 l 0,-30.7 C 273,97.29 249,67.51 220,67.51 Z" />
  <circle class="f1" cx="46" cy="58" r="20" />
  <circle class="f1" cx="96" cy="105" r="14" />
  <circle class="f1" cx="121" cy="42" r="16" />
</svg>

SVG mit CSS und Javascript animieren

Es gibt nur wenige CSS-Events, die eine CSS-Animation starten (so wie in diesem einfachen Beispiel ein Hovern mit der Maus über die Seifenblasen).

Ein kleines Javascript hilft der Animation von SVG-Elementen auf die Beine:

<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 299.5 299.5">
   <style>.frose { fill: hsl(10,50%,90%); transition: fill 2s}.toggle { fill: hsl(5,50%,50%); transition: fill 2s}</style>
      <path style="fill:#aaa" d="m 220,67.51 c -23,0 -42,16.78 -50,40.59 l 22,0 c 5,-11.31 15,-18.51 26,-18.51 c 18,0 32,19.91 32,44.51 l 0,17.3 l -217,0 c -9,0 -15,6.9 -15,15.7 l 0,1.3 c 0,8.7 6,15.7 15,15.7 l 6,0 c 2,27.6 17,50.9 38,63.5 l -3,15.1 c -3,6.3 2,12.8 7,14.4 c 6,1.8 12,-1.9 15,-8.4 l 4,-12.6 c 3,0.9 8,1.4 13,1.4 l 81,0 c 6,0 11,-0.6 14,-1.8 l 5,13.1 c 2,6.5 8,10.2 14,8.6 c 7,-1.9 10,-8.2 9,-14.6 l -5,-16.3 c 17,-10.2 28,-26.9 34,-46.7 l 0,-0.1 c 5,-10.1 8,-22.1 8,-34.8 l 0,-30.7 C 273,97.29 249,67.51 220,67.51 Z" />
      <circle class="frose" cx="46" cy="58" r="20" /><circle class="frose" cx="96" cy="105" r="14" /><circle class="frose" cx="121" cy="42" r="16" />
      <script>
         <![CDATA[
         var frose = document.querySelectorAll(".frose");
         var len = frose.length;
         for (var i=0; i<len; i++) {
         frose[i].onmouseover = function () {
            this.classList.toggle("toggle");
         }
         frose[i].onmouseout = function () {
            this.classList.toggle("toggle");
         }
      }
      ]]>
   </script>
</svg>

Auch diese Lösung hat einen Haken: SVG-Animationen mit Javascript funktionieren nicht, wenn SVG als Datei mit einem img-Tag geladen wird. Das SVG-Bild wird zwar angezeigt, aber Animation springt nicht an.

<img src="css-animate-svg.svg" width="300" height="300">

SVG-Animationen aus SVG-Dateien müssen mit einem HTML iframe oder object in die Webseite geladen werden, damit Animationen mit Javascript ausgeführt werden.

CSS Transform auf SVG

CSS Transformationen arbeiten auf SVG- genauso wie auf HTML-Elementen: Beispiel.

Hier animieren CSS und Javascript nur ein schlichtes transform: rotate().

<script>
<![CDATA[
(function() {
	var d1 = document.getElementById('dolphin');
	var y = 0;
	d1.setAttribute('transform','translate(180,190) rotate(0)');
	var dolphin = setInterval (function () {
		d1.setAttribute('transform', 'translate(180,190) rotate(' + y + ')');
		y = y-3;
	},60);
	dolphin();
} () );
]]>
</script>

Wenn Javascript in SVG gesetzt wird (z.B. um es in einem HTML-iframe aufzurufen), muss es in <![CDATA[ … ]]> gewickelt werden.

SVG-Line-Animationen mit Vivus

Vivus ist eine bezaubernde kleine Library, die SVG Line-Animationen umsetzt und die Grafik on the fly zeichnet. Vivus ist auf SVG-line-Animationen spezialisiert, ist unabhängig von anderen Librarys und bringt gerade mal 11 KB Zusatzgewicht.

Jedes SVG path hat zwei zusätzliche data-Attribute: data-start und data-duration, die eine Timeline defininieren.

<path id="boot" data-start="75" data-duration="50" d="" />
<path id="welle" data-start="70" data-duration="50" d="" />
<path id="welle2" data-start="60" data-duration="50" d="" />
<path data-start="40" data-duration="50" d="" />
<path data-start="0" data-duration="50" d="" />

Nur noch die Animation starten:

boot = new Vivus('boot', {type: 'scenario', duration: 100});

Vivus von maxwellito auf Github

SVG mit Velocity.js

Velocity ist eine Library, die auf jQuery aufsetzt, aber auch ohne jQuery agiert. Auch wenn Velocity ohne jQuery $.animate() benutzt wird, bleibt die Syntax fast gleich und verschiebt nur alle Argumente um eins nach rechts, um dem animierten Element Platz zu machen.

RESTART

Reminiszenz: SVG Animationen mit SMIL

SMIL hatte neben einer überwältigenden Menge an Optionen einen Pluspunkt: SMIL war "All in one". Ein externes animiertes SVG enthielt alle erforderlichen Elemente und Animationen und kam mit einem einfachen img-Tag aus.

Zusammen können SVG und Javascript zwar auch einen großen Umfang animieren, aber die Optionen stehen mit CSS und Javascript nur bei Inline-SVG zur Verfügung.

Für Effekte, die mit CSS und Javascript nicht einfach umzusetzen sind, müssen Libraries wie Vivus und Velocity (klein und leicht) oder à la Snap.svg und GreenSocks einspringen.

Es gibt zwar viele Ansätze als Ersatz von SMIL, aber entweder sind sie lückenhaft oder der Einsatz einer umfassenden Library ist gefragt.

SVG animate (expired / abgelaufen)

Um ein SVG-Element zu animieren, wird ein animate-Tag zwischen das öffnende und schließende Tag gesetzt. Das animate-Tag kommt in vier Variationen:

  1. animate kann jedes skalierbare Attribut animieren.
  2. animateMotion bewegt ein Element auf einem Pfad,
  3. animateTransform animiert Größe, Lage und Rotation
  4. set

Darüber können zwei Animationselemente bzw. Attribute verwendet werden.

  1. animateTransform
  2. mpath
animateMotion
<rect x="" y="" … >
    <animateMotion values="-200,0; 2500,0"  …/>
</rect>

<rect x="" y="" … >
    <animateMotion …>
        <mpath xlink:href="#p1" />
    </animateMotion>
</rect>
animateTransform (translate | scale | rotate | skewX | skewY)
<rect x="" y="" … >
    <animateTransform type="rotate"  …/>
</rect>
animate Attribute
<rect x="" y="" … >
    <animate attributeName="x"  …/>
</rect>
Set – einfaches Toggeln
<rect x="" y="" … >
    <set  …/>
</rect>

animateMotion

Bewegung entlang eines Pfades. Ändert das Koordinatensystem des animierten Objekts. Im einfachsten Fall wird der Pfad im values-Attribut des animateMotion-Tags als Punktefolge angegeben.

(0,0) (450,0) (200,150)
<circle cx="50" cy="50" r="50" fill="ivory">
   <animateMotion dur="10s" 
      values="0,0; 450,0; 200,150; 0,0" 
      repeatCount="indefinite" />
</circle>
path
überschreibt andere Bewegungen wie from, to, by, values, ist absolut oder relativ
calcMode
paced
bei paced werden keyTimes und keySplines ignoriert. Die Punkte eines Splines werden durch das keyTimes-Attribut festgelegt
keyPoints
Semikolon-getrennte Liste mit Werten zwischen 0 und 1
Die Zahl der keyPoints kann von der Zahl der Knoten auf dem Animationspfad (value) abweichen und die keyPoints können in beliebiger Reihenfolge stehen, um vorwärts- / rückwärts-Bewegungen zu erzeugen
repeatCount
# | indefinite
Legt fest, wie oft die Animation wiederholt wird.
rotate
angle | auto | auto-reverse
Ob das Objekt entlang des Animationspfads rotiert wird. Bei auto liegt die x-Achse des Objekts parallel zum Pfad.
values
Semikolon-getrennte Liste von Werten für ein Attribut

Ein komplexer Animationspfad kann auch in ein defs-Element gesetzt werden. animateMotion muss dann einen Link auf den Animationspfad setzen.

<svg xmlns:xlink="http://www.w3.org/1999/xlink" … >
</svg>
<defs>
    <path id="p1"  d="…" />
</defs>
<path d="…" style="fill:#666">
    <animateMotion dur="50" repeatCount="indefinite">
        <mpath xlink:href="#p1"/>
    </animateMotion>
</path>

Wenn die SVG-Grafik nicht inline im HTML-Dokument liegt, braucht das svg-Element eine Referenz auf den xlink-Namespace.

animateTransform

type
translate | scale | rotate | skewX | skew>
Legt fest, welche Transformation animiert wird

Der Nullpunkt des SVG-Koordinatensystems liegt oben links. Um ein Element um seinen Pivotpunkt (Mittelpunkt) zu rotieren, braucht das Element – in diesem Beispiel ein Viereck – ein eigenes Koordinatensystem durch <g transform="translate( 250,125)">.

(250,125)
<g transform="translate( 250,125)">
   <rect x="-75" y="-75" width="150" height="150" fill="ivory">
   <animateTransform repeatCount="indefinite"
      attributeName="transform" type="rotate"
      from="0" to="90" begin="0" dur="5s" />
   </rect>
</g>

Leider gibt es kein einfaches »back and forth« in SMIL. Stattdessen wird die Animation in zwei Schritte unterteilt, die miteinander synchronisiert werden.

<animateTransform id="m1" 
    attributeName="transform" type="rotate" 
    from="0" to="20" begin="0;m2.end" dur="4s" />
<animateTransform id="m2" 
    attributeName="transform" type="rotate" 
    from="20" to="0" begin="m1.end" dur="4s" />

set

set ist eine Kurzschrift für animate und erzeugt eine Animation mit einer Dauer von 0s. Ein dur-Attribut mit einem anderen Wert als 0 hat keine Wirkung. Der neue Wert wird sofort zugewiesen, wenn die Animation durch ein Event ausgelöst wird.

Kurz: set toggelt zwischen zwei Zuständen.

<set attributeName="display" to="none" begin="off.end" />

set ist nützlich, um nichtnumerische Attribute wie visibility verändern oder zwischen display:block und display:none zu wechseln..