about-svg.de

SVG animieren mit SMIL und CSS

Teil 4: Animation · Kapitel 10 von 12 · Aktualisiert am · 4 Minuten Lesezeit

SVG kann sich bewegen, ganz ohne JavaScript. Die Animationselemente stammen aus SMIL, einem älteren W3C-Standard für Multimedia, und werden direkt in die Grafik geschrieben.

Das Prinzip

Eine Animation steht als Kind in dem Element, das sich verändern soll. Sie nennt das Attribut, das animiert wird (attributeName), den Start- und Endwert (from und to oder eine Liste in values) und die Dauer (dur). Mit repeatCount="indefinite" läuft sie endlos, mit fill="freeze" bleibt sie am Ende stehen, statt zurückzuspringen.

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 120" width="220" height="132">
  <circle cx="100" cy="60" r="30" fill="#1f5fd1">
    <animate attributeName="r" values="30;45;30" dur="2.4s" repeatCount="indefinite"/>
    <animate attributeName="fill" values="#1f5fd1;#c2410c;#1f5fd1" dur="2.4s" repeatCount="indefinite"/>
  </circle>
</svg>
Ein Kreis, dessen Radius und Farbe mit animate pulsieren. values mit drei Einträgen sorgt für Hin- und Rückweg.

Für Farbverläufe über die Zeit gab es früher ein eigenes Element namens animateColor. Es galt schon in der zweiten Ausgabe von SVG 1.1 als veraltet und ist in SVG 2 entfallen. Ein normales animate auf fill oder stroke kann das genauso, wie das Beispiel zeigt.

Drehen, schieben, skalieren: animateTransform

Das Attribut transform lässt sich nicht mit einem einfachen animate verändern, weil es aus Funktionen besteht. Dafür gibt es animateTransform mit einem zusätzlichen type: rotate, translate, scale, skewX oder skewY. Bei einer Drehung enthalten die Werte Winkel und Drehpunkt.

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 220 120" width="242" height="132">
  <defs>
    <g id="an-zahnrad">
      <circle r="26"/>
      <g>
        <rect x="-6" y="-36" width="12" height="14"/><rect x="-6" y="22" width="12" height="14"/>
        <rect x="-36" y="-6" width="14" height="12"/><rect x="22" y="-6" width="14" height="12"/>
        <rect x="-6" y="-36" width="12" height="14" transform="rotate(45)"/><rect x="-6" y="22" width="12" height="14" transform="rotate(45)"/>
        <rect x="-36" y="-6" width="14" height="12" transform="rotate(45)"/><rect x="22" y="-6" width="14" height="12" transform="rotate(45)"/>
      </g>
      <circle r="9" fill="#fbfcfd"/>
    </g>
  </defs>
  <g transform="translate(90 60)">
    <use href="#an-zahnrad" fill="#1f5fd1">
      <animateTransform attributeName="transform" type="rotate" from="0" to="360" dur="6s" repeatCount="indefinite"/>
    </use>
  </g>
  <g transform="translate(158 40) scale(0.6)">
    <use href="#an-zahnrad" fill="#c2410c">
      <animateTransform attributeName="transform" type="rotate" from="22.5" to="-337.5" dur="3.6s" repeatCount="indefinite"/>
    </use>
  </g>
</svg>
Ein Zahnrad dreht sich mit animateTransform um seinen Mittelpunkt (100|60), ein kleineres läuft gegenläufig mit.

Bewegung entlang eines Pfads: animateMotion

animateMotion führt ein Element über eine Bahn, die du im Attribut path oder über ein Kindelement <mpath href="#id"/> angibst. Mit rotate="auto" dreht sich das Element in Bewegungsrichtung, wie ein Auto, das einer Straße folgt. Die Pfadbefehle sind dieselben wie im Kapitel über Pfade.

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 140" width="320" height="140">
  <path id="an-bahn" d="M 20 110 C 80 -10, 160 160, 300 30" fill="none" stroke="#9aa3b2" stroke-width="2" stroke-dasharray="5 5"/>
  <path d="M -10 -7 L 12 0 L -10 7 Z" fill="#c2410c">
    <animateMotion dur="4s" repeatCount="indefinite" rotate="auto">
      <mpath href="#an-bahn"/>
    </animateMotion>
  </path>
</svg>
Ein Pfeil folgt einer Kurve und dreht sich mit rotate="auto" in Fahrtrichtung.

Zeitsteuerung

Das Attribut begin legt fest, wann eine Animation startet. Möglich sind Zeitangaben wie 2s, Ereignisse wie click oder Bezüge auf andere Animationen, etwa begin="kreis1.end". Damit lassen sich Abläufe verketten, ohne eine Zeile Skript zu schreiben. Mit keyTimes und keySplines bei calcMode="spline" steuerst du das Tempo, also ob eine Bewegung sanft beschleunigt oder abbremst. <set> schließlich setzt einen Wert schlagartig, ohne Übergang, zum Beispiel um ein Element nach drei Sekunden sichtbar zu machen.

Die Alternative: CSS

Inline eingebettete SVG-Elemente lassen sich auch mit CSS-Transitions und Keyframes animieren, genau wie HTML. Das ist für Hover-Effekte bei Icons der einfachste Weg. Animierbar sind vor allem Transformationen, Deckkraft, Farben und Strichangaben. Ein bekannter Trick ist eine Linie, die sich selbst zeichnet: stroke-dasharray und stroke-dashoffset werden auf die Länge des Pfads gesetzt und der Offset dann auf null animiert.

.unterschrift path {
  stroke-dasharray: 600;
  stroke-dashoffset: 600;
  animation: zeichnen 3s ease-out forwards;
}
@keyframes zeichnen { to { stroke-dashoffset: 0; } }

@media (prefers-reduced-motion: reduce) {
  .unterschrift path { animation: none; stroke-dashoffset: 0; }
}

Bei CSS-Transformationen an SVG-Elementen gibt es eine Falle: Der Drehpunkt liegt standardmäßig im Ursprung der Zeichenfläche, nicht in der Mitte der Form. Mit transform-box: fill-box und transform-origin: center dreht sich die Form um sich selbst.

Wie es um SMIL steht

Das Chrome-Team hatte 2015 angekündigt, SMIL-Animationen aus dem Browser zu entfernen, und diese Ankündigung später wieder zurückgezogen. Heute unterstützen alle großen Browser SMIL in SVG. Der einzige Browser, der es nie konnte, war der Internet Explorer.

Rücksicht auf Bewegungsempfindliche

Manche Menschen reagieren auf Bewegung am Bildschirm mit Schwindel oder Übelkeit und stellen in ihrem System „Bewegung reduzieren“ ein. CSS-Animationen kannst du über die Medienabfrage prefers-reduced-motion abschalten, wie im Beispiel oben. SMIL-Animationen reagieren darauf nicht von selbst. Für dauerhafte Bewegung ist es deshalb besser, sie nur einmal oder auf Klick abzuspielen, statt endlos. Wer volle Kontrolle braucht, etwa Pause, Zurückspulen oder Reaktion auf Scrollen, greift zu JavaScript, wie im nächsten Kapitel SVG und JavaScript.

Zum Weiterlesen