SVG mit CSS und Javascript animieren

SVG mit CSS-Keyframes Animation

CSS animiert SVG genauso wie HTML-Elemente: alle Eigenschaften, die in einem style-Attribut stehen können, können mit CSS animiert werden. Wo CSS an die Grenzen stößt, hilft Javascript nach. SVG unterstützt CSS und kann im style-Attribut dekorative Eigenschaften wie fill, opacity, stroke, stroke-width und font-family zusammenfassen.

23-02-02 SITEMAP CSS HTML JS Basis JS Web Tutorial SVG

SVG animieren – drei Techniken

Auch wenn SVG mit SMIL ein eigenes Animationsmodell hat – SMIL-Animationen wurden von IE in allen Versionen nicht unterstützt. Seit der Ankündigung der Entwickler, dass Chrome SMIL nicht länger unterstützen wolle, sitzen SVG-Animationen auf einem Ersatzteillager.

CSS kann SVG ebenfalls animieren, wobei SVG-Geometrie-Attribute wie x, y, width, height, r, rx, ry und SVG transform allerdings außen vor bleiben. Sie lassen sich nicht im style-Attribut zusammenfassen. An diesen Stellen muss Javascript eingreifen.

CSS-Animationen

Nur Eigenschaften, die als CSS notiert werden können

Wird in externen SVG-Dateien ausgeführt

Javascript-Animationen

Alle Eigenschaften und alle Geometrie-Attribute.

Wird in externen SVG-Dateien nicht ausgeführt.

SMIL-Animationen

Alle Eigenschaften und alle Geometrie-Attribute

Wird in externen SVG-Dateien ausgeführt

Allerdings haben SVG-Animationen mit Javascript einen Haken: Sie funktionieren nicht wie SMIL-Animationen in externen SVG-Dateien. SVG-Animationen mit Javascript müssen inline ins HTML oder mit einem HTML iframe bzw. object in die Webseite geladen werden, damit Animationen mit Javascript ausgeführt werden.

Die SVG-Grafik wird zwar angezeigt, aber Javascript wird nicht ausgeführt, die Animation springt nicht an.

CSS Transform auf SVG

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

SVG CSS transform-Animation

Hier animiert CSS in der SVG-Datei ein schlichtes transform: rotate().

Der Trick bei der Rotation mit CSS Keyframes liegt im Ursprung der Transformation. Quelle Rotating a SVG path using CSS3 around its own center auf stackoverflow.com

#dolphin {
	animation: turning 5s infinite linear;
	transform-origin: 170 170;
}

@keyframes turning {
	from {transform: rotate(0)}
	to {transform: rotate(-360deg) }
}

transform-origin und transform-box

SVG-Elemente mit CSS zu rotieren ist ein Hexenkessel. CSS transform:rotate (xdeg) rotiert ein Element im Uhrzeigersinn um seinen Mittelpunkt, SVG-Elemente rotieren um den Nullpunkt der ViewBox oben links.

.rocket {
	transform-origin: 50% 50%;
transform-origin: 75% 120%;
transform-box: fill-box;
animation: rocket 3s linear infinite; } @keyframes rocket { to { transform: rotate(359deg)} }
SVG SMIL Animationen
CSS transform-origin: 50% 50%;
CSS transform-origin: 75% 120%;
CSS transform-box: fill-box;

CSS transform-origin: 50% 50%; oder transform-origin: center; setzt den Mittelpunkt der Rotation auf den Mittelpunkt der ViewBox. 50% oder center sind relative Werte. Absolute Werte wie transform-origin: 200px 121px würden in einem responsiven SVG, dessen Abmessungen vom Viewport des Browsers abhängen, immer wieder daneben liegen.

Damit die Rakete um den Mond kreist, braucht sie nur die relativen Koordinaten des Mittelpunkts des Monds: transform-origin: 75% 120%; (denn der Mittelpunkt des Monds liegt außerhalb der Viewbox der Grafik).

Werte für CSS transform-box für SVG-Elemente

transform-box: fill-box
Die Object Bounding Box des Elements
transform-box: stroke-box
Die Stroke Bounding Box des Elements
transform-box: view-box
Der SVG-Viewport – default-Wert

SVG mit SMIL animieren

Auch wenn SMIL zwischenzeitlich todgesagt wurde – SMIL wird heute wieder von allen modernen Browsern unterstützt. Das SVG-eigene Animationsmodell SMIL hat eine leichte Ähnlichkeit mit CSS-Keyframes, aber anstelle von CSS-Stilen verwendet SMIL spezielle SVG-Elemente wie <animateTransform … />.

<div class="turtle">
	<div class="crossing">
	 …
	</div>
</div>
SVG SMIL Animation

SVG-Lineart mit CSS

Selbst Lineart-Animationen lassen sich mit CSS-Keyframes umsetzen.

CSS-Keyframes-Animation schaukelndes Boot
<style>
#boot {
	stroke: hsl(200,50%,50%);
	stroke-dasharray: 0;
	animation: dashdraw 3s 2s linear reverse forwards;
}

@keyframes dashdraw {
	from {stroke-dashoffset: 0;   stroke: #fff }
	to   {stroke-dashoffset: 396; stroke: hsl(200,50%,50%) }
}
</style>

<path id="boot" d="m 356.2,140.6 … …" 
		style="stroke-dasharray: 225px, 225px; stroke-dashoffset: 0px;"/>

Ähnlich wie CSS border hat SVG ein Attribut stroke-dasharray, mit dem der Stroke gestrichelt wird, und das als CSS-Eigenschaft geschrieben werden kann. Was als style notiert werden kann, läßt sich mit CSS animieren.

Die Grafik-Datei ist Javascript-frei. Allerdings müssen vor dem Speichern der SVG-Datei ein paar Zeilen Javascript die Länge des animierten Pfads berechnen.

let draw = document.querySelector('#boot');
console.log (draw.getTotalLength());

Die Länge des Pfads in der Console auslesen und in das style-Attribut übernehmen (mehr zu SVG-Pfad-Animationen).

Alternativ: Vivus von maxwellito auf Github ist eine bezaubernde kleine Library, die SVG Lineart-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.

SVG mit Velocity.js

Velocity.js ist eine Library für Animationen mit Javascript, 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.

Velocity (circle[0], 
		   {fill: "#efefef", opacity: 1, r: 35}, 
		   {delay: 1000, duration: 2000, easing: "swing"});

Warum nicht mit CSS Keyframes? CSS Keyframes-Animationen haben keine einfache Möglichkeit, die Keyframes der vier Blöcke miteinander zu synchronisieren. CSS animation-delay könnte zwar einspringen, aber dann fehlt immer noch das Animation Reset und Neustart in CSS.

Wie wäre es mit dem Web Animation API für Javascript? Javascript animate() lehnt sich eng an CSS Keyframes-Animation an.