Update Dezember 2015: Zum Zeitpunkt dieses Updates scheint SMIL etwas am Sterben zu sein. Sarah Drasner hat einen Leitfaden, wie man einige seiner Funktionen ersetzen kann.
Das Folgende ist ein Gastbeitrag von Sara Soueidan. Sara hat ein Talent dafür, tief in Web-Funktionen einzutauchen und sie für den Rest von uns ausführlich zu erklären. Hier taucht sie in SMIL (und Freunde) und die direkt in SVG integrierte Animationssyntax ein und gibt uns diesen epischen Leitfaden.
Inhaltsverzeichnis
- Übersicht
- Warum SVG-Animationen verwenden?
- Browser-Unterstützung und Fallbacks
- Festlegen des Ziels der Animation mit xlink:href
- Festlegen der Zieleigenschaft der Animation mit attributeName und attributeType
- Animieren eines Attributs eines Elements von einem Wert zum anderen über eine bestimmte Zeitspanne und Festlegen des Endzustands: from, by, to, dur und fill
- Animationen entlang beliebiger Pfade: Das Element
- Text entlang eines beliebigen Pfades bewegen
- Transformationen animieren: Das <animatetransform></animatetransform> Element
- Das <set></set> Element
- Elemente, Attribute und Eigenschaften, die animiert werden können
- Schlussworte
Überblick
SVG-Grafiken können mit Animationselementen animiert werden. Die Animationselemente wurden ursprünglich in der SMIL-Animationsspezifikation definiert; diese Elemente umfassen
<animate></animate>– das es Ihnen ermöglicht, skalare Attribute und Eigenschaften über einen Zeitraum hinweg zu animieren.<set></set>– eine praktische Kurzform für animate, nützlich zum Zuweisen von Animationswerten zu nicht-numerischen Attributen und Eigenschaften, wie z.B. der Sichtbarkeitseigenschaft.<animatemotion></animatemotion>– das ein Element entlang eines Bewegungspfades bewegt.<animatecolor></animatecolor>– das den Farbwert bestimmter Attribute oder Eigenschaften über die Zeit ändert. Beachten Sie, dass das Element zugunsten der einfachen Verwendung des animate-Elements zur Zielbestimmung von Eigenschaften, die Farbwerte annehmen können, als veraltet markiert wurde. Obwohl es noch in der SVG 1.1-Spezifikation vorhanden ist, wird deutlich darauf hingewiesen, dass es veraltet ist; und es wurde vollständig aus der SVG 2-Spezifikation entfernt.
Zusätzlich zu den in der SMIL-Spezifikation definierten Animationselementen enthält SVG Erweiterungen, die mit der SMIL-Animationsspezifikation kompatibel sind; diese Erweiterungen umfassen Attribute, die die Funktionalität des Elements erweitern, sowie zusätzliche Animationselemente. Die SVG-Erweiterungen umfassen
<animatetransform></animatetransform>– ermöglicht es Ihnen, eines der SVG-Transformationsattribute über die Zeit zu animieren, wie z.B. dastransform-Attribut.path(Attribut) – ermöglicht die Angabe jedes Merkmals der SVG-Pfaddatensyntax in einem path-Attribut desanimateMotion-Elements (SMIL Animation erlaubt nur eine Untermenge der SVG-Pfaddatensyntax innerhalb eines path-Attributs). Wir werden später mehr überanimateMotionsprechen.<mpath></mpath>– wird in Verbindung mit demanimateMotion-Element verwendet, um einen Bewegungspfad zu referenzieren, der als Pfad für die Bewegung verwendet werden soll. Das mpath-Element ist innerhalb desanimateMotion-Elements, vor dem schließenden Tag, enthalten.keypoints(Attribut) – wird als Attribut füranimateMotionverwendet, um eine präzise Kontrolle der Geschwindigkeit von Bewegungspfad-Animationen zu ermöglichen.rotate(Attribut) – wird als Attribut füranimateMotionverwendet, um zu steuern, ob ein Objekt automatisch so gedreht wird, dass seine x-Achse in die gleiche Richtung (oder entgegengesetzte Richtung) wie der gerichtete Tangentenvektor des Bewegungspfades zeigt. Dieses Attribut ist der Schlüssel, damit die Bewegung entlang eines Pfades wie erwartet funktioniert. Mehr dazu im AbschnittanimateMotion.
SVG-Animationen können aufgrund ihrer Natur CSS-Animationen und Übergängen ähneln. Keyframes werden erstellt, Dinge bewegen sich, Farben ändern sich usw. Sie können jedoch Dinge tun, die CSS-Animationen nicht können, was wir behandeln werden.
Warum SVG-Animationen verwenden?
SVGs können mit CSS gestaltet und animiert werden (Folien). Grundsätzlich können alle Transformations- oder Übergangsanimationen, die auf ein HTML-Element angewendet werden können, auch auf ein SVG-Element angewendet werden. Es gibt jedoch einige SVG-Eigenschaften, die nicht über CSS, aber über SVG animiert werden können. Ein SVG-Pfad beispielsweise kommt mit einem Satz von Daten (einem d=""-Attribut), die die Form des Pfades definieren. Diese Daten können über SMIL, aber nicht über CSS modifiziert und animiert werden. Der Grund dafür ist, dass SVG-Elemente durch eine Reihe von Attributen, bekannt als SVG-Präsentationsattribute, beschrieben werden. Einige dieser Attribute können mit CSS gesetzt, modifiziert und animiert werden, andere nicht.
Viele Animationen und Effekte lassen sich derzeit also einfach nicht mit CSS umsetzen. Die Lücken bei SVG-Animationen in CSS können entweder mit JavaScript oder den deklarativen SVG-Animationen, die von SMIL abgeleitet sind, geschlossen werden.
Wenn Sie JavaScript bevorzugen, empfehle ich snap.svg von Dmitry Baranovsky, das als „das jQuery von SVG“ beschrieben wird. Hier ist eine Sammlung von Beispielen dazu.
Oder wenn Sie einen deklarativeren Animationsansatz bevorzugen, können Sie die SVG-Animationselemente verwenden, wie wir in diesem Leitfaden behandeln werden!
Ein weiterer Vorteil von SMIL gegenüber JS-Animationen ist, dass JS-Animationen nicht funktionieren, wenn die SVG als img eingebettet oder als background-image in CSS verwendet wird. SMIL-Animationen funktionieren in beiden Fällen (oder sollten, je nach Browser-Unterstützung). Das ist meiner Meinung nach ein großer Vorteil. Es kann sein, dass Sie SMIL anderen Optionen vorziehen, genau deswegen. Dieser Artikel ist ein Leitfaden, der Ihnen helfen soll, SMIL noch heute zu verwenden.
Browser-Unterstützung und Fallbacks
Die Browser-Unterstützung für SMIL-Animationen ist recht gut. Sie funktionieren in allen Browsern außer im Internet Explorer und Opera Mini. Eine gründliche Übersicht über die Browser-Unterstützung finden Sie in der Kompatibilitätstabelle auf Can I Use.
Wenn Sie einen Fallback für SMIL-Animationen bereitstellen müssen, können Sie die Browser-Unterstützung dynamisch mit Modernizr testen. Wenn SMIL nicht unterstützt wird, können Sie dann eine Art Fallback bereitstellen (JavaScript-Animationen, eine alternative Erfahrung usw.).
Festlegen des Ziels der Animation mit xlink:href
Egal welches der vier Animationselemente Sie wählen, Sie müssen das Ziel der durch dieses Element definierten Animation festlegen.
Um ein Ziel festzulegen, können Sie das Attribut xlink:href verwenden. Das Attribut nimmt eine URI-Referenz auf das Element entgegen, das das Ziel dieser Animation ist und daher im Laufe der Zeit modifiziert wird. Das Zielelement muss Teil des aktuellen SVG-Dokumentfragments sein.
<rect id="cool_shape" ...="">
<animate xlink:href="#cool_shape" ...=""></animate>
</rect>
Wenn Sie schon einmal auf SVG-Animationselemente gestoßen sind, haben Sie sie wahrscheinlich verschachtelt innerhalb des Elements gesehen, das sie animieren sollen. Dies ist auch gemäß der Spezifikation möglich
Wird das Attribut
xlink:hrefnicht angegeben, so ist das Zielelement das direkte Elternelement des aktuellen Animationselements.
<rect id="cool_shape" ...="">
<animate ...=""></animate>
</rect>
Wenn Sie also die Animation in dem Element „kapseln“ möchten, auf das sie sich bezieht, können Sie das tun. Und wenn Sie die Animationen separat an einem anderen Ort im Dokument aufbewahren möchten, können Sie das auch tun und das Ziel jeder Animation mit xlink:href angeben. Beide Wege funktionieren einwandfrei.
Festlegen der Zieleigenschaft der Animation mit attributeName und attributeType
Alle Animationselemente teilen auch ein weiteres Attribut: attributeName. Das Attribut attributeName wird verwendet, um den Namen des Attributs anzugeben, das Sie animieren.
Wenn Sie beispielsweise die Position der Mitte eines Kreises auf der x-Achse animieren möchten, tun Sie dies, indem Sie cx als Wert für das Attribut attributeName angeben.
attributeName akzeptiert nur einen Wert, keine Liste von Werten, Sie können also immer nur ein Attribut gleichzeitig animieren. Wenn Sie mehr als ein Attribut animieren möchten, müssen Sie für das Element mehrere Animationen definieren. Das ist etwas, das ich mir anders wünschen würde und bei dem ich denke, dass CSS einen Vorteil gegenüber SMIL hat. Aber andererseits, aufgrund der möglichen Werte für andere Animationsattribute (die wir als Nächstes behandeln werden), macht es nur Sinn, jeweils nur einen Attributnamen zu definieren, sonst könnten die anderen Attributwerte zu komplex werden, um damit zu arbeiten.
Wenn Sie den Attributnamen angeben, können Sie ein XMLNS-Präfix (kurz für XML-Namensraum) hinzufügen, um den Namensraum des Attributs anzugeben. Der Namensraum kann auch mit dem Attribut attributeType angegeben werden. Zum Beispiel sind einige Attribute Teil des CSS-Namensraums (was bedeutet, dass das Attribut auch als CSS-Eigenschaft gefunden werden kann) und andere sind nur XML. Eine Tabelle, die diese Attribute zeigt, finden Sie hier. Die Attribute in der Tabelle sind nicht alle SVG-Attribute. Es sind nur die, die mit CSS gesetzt werden können. Einige davon sind bereits als CSS-Eigenschaften verfügbar.
Wird der Wert für attributeType nicht explizit gesetzt oder ist er auf auto gesetzt, muss der Browser zuerst die Liste der CSS-Eigenschaften nach einem passenden Eigenschaftsnamen durchsuchen, und wenn keiner gefunden wird, den Standard-XML-Namensraum für das Element durchsuchen.
Zum Beispiel animiert der folgende Code-Schnipsel die opacity eines SVG-Rechtecks. Da das opacity-Attribut auch als CSS-Eigenschaft verfügbar ist, wird der attributeType auf den CSS-Namensraum gesetzt
<rect>
<animate
attributetype="CSS"
attributename="opacity"
from="1"
to="0"
dur="5s"
repeatcount="indefinite">
</animate>
</rect>
Wir werden die anderen Animationsattribute in den folgenden Beispielen behandeln. Sofern nicht anders vermerkt, sind alle Animationsattribute allen Animationselementen gemeinsam.
Animieren eines Attributs eines Elements von einem Wert zum anderen über eine Zeitspanne und Festlegen des Endzustands: from, by, to, dur und fill
Beginnen wir damit, einen Kreis von einer Position zur anderen zu bewegen. Wir werden dies tun, indem wir den Wert seines cx-Attributs (das die x-Position seines Mittelpunkts angibt) ändern.
Wir werden das Element verwenden, um dies zu tun. Dieses Element wird verwendet, um jeweils ein Attribut zu animieren. Attribute, die numerische Werte und Farben annehmen, werden normalerweise mit animiert. Eine Liste der animierbaren Attribute finden Sie in dieser Tabelle.
Um einen Wert über einen Zeitraum in einen anderen zu ändern, werden die Attribute from, to und dur verwendet. Zusätzlich zu diesen möchten Sie auch angeben, wann die Animation mit dem Attribut begin starten soll.
<circle id="my-circle" r="30" cx="50" cy="50" fill="orange">
<animate xlink:href="#my-circle" attributename="cx" from="50" to="450" dur="1s" begin="click" fill="freeze"></animate>
</circle>
Im obigen Beispiel haben wir einen Kreis definiert und dann eine Animation auf diesen Kreis angewendet. Der Mittelpunkt des Kreises bewegt sich von der ursprünglichen Position bei 50 Einheiten zu 450 Einheiten entlang der x-Achse.
Der Wert von begin ist auf click gesetzt. Das bedeutet, dass der Kreis sich bewegt, wenn er angeklickt wird. Sie können diesen Wert auch auf einen Zeitwert setzen. Zum Beispiel startet begin="0s" die Animation, sobald die Seite geladen ist. Sie können eine Animation verzögern, indem Sie einen positiven Zeitwert festlegen. Zum Beispiel startet begin="2s" die Animation zwei Sekunden nach dem Laden.
Noch interessanter an begin ist, dass Sie Werte wie click + 1s definieren können, um eine Animation eine Sekunde nach dem Klicken auf das Element zu starten! Darüber hinaus können Sie andere Werte verwenden, die es Ihnen ermöglichen, Animationen zu synchronisieren, ohne die Dauer und Verzögerungen anderer Animationen berechnen zu müssen. Mehr dazu später.
Das Attribut dur ähnelt der animation-duration-Entsprechung in CSS.
Die Attribute from und to ähneln den from- und to-Keyframes in einem @keyframe-Block einer Animation in CSS
@keyframes moveCircle {
from { /* start value */ }
to { /* end value */ }
}
Das fill-Attribut (das leider den gleichen Namen wie das fill-Attribut trägt, welches die Füllfarbe eines Elements definiert) ähnelt der animation-fill-mode-Eigenschaft, die angibt, ob das Element nach Beendigung der Animation in seinen Ausgangszustand zurückkehren soll oder nicht. Die Werte in SVG ähneln denen in CSS, verwenden jedoch unterschiedliche Namen
freeze: Der Animationseffekt ist so definiert, dass er den Effektwert beim letzten Wert der aktiven Dauer einfriert. Der Animationseffekt ist für den Rest der Dokumentdauer (oder bis die Animation neu gestartet wird) „eingefroren“.remove: Der Animationseffekt wird entfernt (nicht mehr angewendet), wenn die aktive Dauer der Animation beendet ist. Nach dem aktiven Ende der Animation beeinflusst die Animation das Ziel nicht mehr (es sei denn, die Animation wird neu gestartet).
Versuchen Sie, die Werte in der Live-Demo zu ändern, um zu sehen, wie die Animation beeinflusst wird
Das Attribut by wird verwendet, um einen relativen Versatz für die Animation anzugeben. Wie der Name schon sagt, können Sie damit den Betrag angeben, um den Sie die Animation voranschreiten lassen möchten. Der Effekt von by ist fast nur sichtbar, wenn Sie die Animationsdauer in diskreten Schritten durchlaufen, ähnlich wie es bei der CSS-Funktion steps() funktioniert. Das SVG-Äquivalent zur CSS-Funktion steps() ist calcMode="discrete". Wir werden später im Artikel auf das Attribut calcMode eingehen.
Ein weiterer Fall, in dem der Effekt von by deutlicher wird, ist, wenn Sie nur das Attribut to angeben. Ein Beispiel dafür wäre die Verwendung mit dem set-Element, das wir später im Artikel ebenfalls behandeln werden.
Und zu guter Letzt ist by auch nützlich, wenn Sie mit additiven und akkumulativen Animationen arbeiten. Darauf werden wir später im Artikel eingehen.
Animationen neu starten mit restart
Es kann nützlich sein, zu verhindern, dass eine Animation neu gestartet wird, während sie aktiv ist. Dazu bietet SVG das Attribut restart. Sie können dieses Attribut auf einen von drei möglichen Werten setzen
always: Die Animation kann jederzeit neu gestartet werden. Dies ist der Standardwert.whenNotActive: Die Animation kann nur neu gestartet werden, wenn sie nicht aktiv ist (d.h. nach dem aktiven Ende). Versuche, die Animation während ihrer aktiven Dauer neu zu starten, werden ignoriert.never: Das Element kann für den Rest der aktuellen einfachen Dauer des übergeordneten Zeitcontainers nicht neu gestartet werden. (Im Falle von SVG kann die Animation, da der übergeordnete Zeitcontainer das SVG-Dokumentfragment ist, für den Rest der Dokumentdauer nicht neu gestartet werden.)
Animationen benennen und synchronisieren
Angenommen, wir möchten die Position und die Farbe des Kreises animieren, so dass die Farbänderung am Ende der Bewegungsanimation stattfindet. Wir können das tun, indem wir den begin-Wert der farbändernden Animation gleich der duration der Bewegungsanimation setzen; so würden wir es normalerweise in CSS tun.
SMIL verfügt jedoch über eine nette Ereignisbehandlungsfunktion. Wir haben bereits erwähnt, dass das Attribut begin Werte wie click + 5s akzeptiert. Dieser Wert wird als „Ereigniswert“ bezeichnet und besteht in diesem Fall aus einer Ereignisreferenz, gefolgt von einem „Uhrzeitwert“. Der interessante Teil hier ist die Benennung des zweiten Teils: der „Uhrzeitwert“. Warum ist es nicht einfach ein „Zeitwert“? Nun, die Antwort ist, dass Sie buchstäblich einen Uhrzeitwert wie „10min“ oder „01:33“ verwenden können, was „1 Minute und 33 Sekunden“ entspricht, oder sogar „02:30:03“ (zwei Stunden, 30 Minuten und 3 Sekunden). Zum Zeitpunkt dieses Schreibens sind Uhrzeitwerte noch nicht vollständig in einem Browser implementiert.
Wenn wir also in der vorherigen Demo click + 01:30 verwenden würden, würde die Animation, falls ein Browser dies unterstützen würde, 1 Minute und 30 Sekunden nach dem Klicken auf den Kreis ausgelöst.
Eine weitere Art von Wert, die es akzeptieren kann, ist die ID einer anderen Animation, gefolgt von einer Ereignisreferenz. Wenn Sie zwei (oder mehr) Animationen haben (egal ob sie auf dasselbe Element angewendet werden oder nicht!) und Sie diese synchronisieren möchten, so dass eine von ihnen relativ zur anderen startet, können Sie dies tun, ohne die Dauer der anderen Animation kennen zu müssen.
Im nächsten Demo beginnt das blaue Rechteck beispielsweise 1 Sekunde nach dem Start der Kreisanimation. Dies geschieht, indem jeder Animation eine ID zugewiesen und diese ID dann mit dem begin-Ereignis wie im folgenden Code gezeigt verwendet wird
<circle id="orange-circle" r="30" cx="50" cy="50" fill="orange">
<rect id="blue-rectangle" width="50" height="50" x="25" y="200" fill="#0099cc"></rect>
<animate
xlink:href="#orange-circle"
attributename="cx"
from="50"
to="450"
dur="5s"
begin="click"
fill="freeze"
id="circ-anim">
</animate>
<animate
xlink:href="#blue-rectangle"
attributename="x"
from="50"
to="425"
dur="5s"
begin="circ-anim.begin + 1s"
fill="freeze"
id="rect-anim">
</animate>
</circle>
Das begin="circ-anim.begin + 1s" ist der Teil, der dem Browser anweist, die Animation des Rechtecks 1 Sekunde nach dem Beginn der Kreisanimation zu starten. Sie können die Live-Demo ausprobieren
Sie können die Rechteckanimation auch nach dem Ende der Kreisanimation mit dem end-Ereignis starten
<animate
xlink:href="#blue-rectangle"
attributename="x"
from="50"
to="425"
dur="5s"
begin="circ-anim.end"
fill="freeze"
id="rect-anim">
</animate>
Man könnte es sogar vor dem Ende der Kreisanimation starten
<animate
xlink:href="#blue-rectangle"
attributename="x"
from="50"
to="425"
dur="5s"
begin="circ-anim.end - 3s"
fill="freeze"
id="rect-anim">
</animate>
Animationen wiederholen mit repeatCount
Wenn Sie eine Animation mehr als einmal ausführen möchten, können Sie dies mit dem Attribut repeatCount tun. Sie können die Anzahl der Wiederholungen angeben oder das Schlüsselwort indefinite verwenden, um sie endlos wiederholen zu lassen. Wenn wir also die Animation des Kreises zweimal wiederholen wollten, würde der Code wie folgt aussehen
<animate
xlink:href="#orange-circle"
attributename="cx"
from="50"
to="450"
dur="5s"
begin="click"
repeatcount="2"
fill="freeze"
id="circ-anim">
</animate>
Die Live-Demo dazu können Sie hier ansehen. In der Demo habe ich die Wiederholungsanzahl für den Kreis auf 2 und für das Quadrat auf indefinite gesetzt.
Beachten Sie, dass die Animation vom anfänglichen from-Wert neu startet, anstatt von dem Wert, den sie am Ende der Animation erreicht hat. Leider enthält SMIL keine Möglichkeit, wie bei CSS-Animationen zwischen Start- und Endwerten hin und her zu wechseln. In CSS gibt die Eigenschaft animation-direction an, ob eine Animation in einigen oder allen Zyklen oder Iterationen rückwärts abgespielt werden soll. Der Wert animation-direction: alternate bedeutet, dass die Animationszyklus-Iterationen mit ungeraden Zählungen in normaler Richtung abgespielt werden und die Animationszyklus-Iterationen mit geraden Zählungen in umgekehrter Richtung. Das bedeutet, dass der erste Zyklus von Anfang bis Ende abgespielt wird, dann der zweite Zyklus vom Ende zurück zum Anfang, dann der dritte Zyklus von Anfang bis Ende und so weiter.
In SMIL müsste man dazu JavaScript verwenden, um die Werte der from- und to-Attribute explizit zu ändern. Jon McPartland von Big Bite Creative schrieb vor einiger Zeit einen Beitrag, in dem er erklärte, wie er dies für eine Menüsymbolanimation tat, an der er arbeitete.
Ein weiterer Workaround besteht darin, den Endwert als Mittelwert anzugeben und dann den Endwert gleich dem Anfangswert zu setzen. Sie können beispielsweise die Animation so einstellen, dass sie from einem Wert beginnt und mit to am selben Wert endet, außer dass Sie das, was Sie eigentlich als Endwert festgelegt hätten, als Zwischenwert zwischen from und to angeben.
In CSS würden wir das ungefähr so machen
@keyframes example {
from, to {
left: 0;
}
50% {
left: 300px;
}
}
Das Äquivalent in SMIL ist die Verwendung des Attributs values, das wir gleich erklären werden.
Dennoch kann der obige Workaround je nach Art der gewünschten Animation und ob Sie Animationen verketten, wiederholen oder additive Animationen durchführen, funktionieren oder auch nicht.
Hier ist eine schöne, einfache unendliche Animation mit verzögerten Startzeiten von Miles Elam
Wiederholungszeit beschränken mit repeatDur
Eine unendliche Wiederholung eines Elements kann lästig oder benutzerunfreundlich werden, wenn die Animation lange Zeit dauert. Es kann daher eine gute Idee sein, die Wiederholungszeit auf einen bestimmten Zeitraum zu beschränken und die Wiederholung nach einer bestimmten Zeit relativ zum Beginn des Dokuments zu stoppen. Dies wird als Präsentationszeit bezeichnet.
Die Präsentationszeit gibt die Position in der Zeitleiste relativ zum Dokumentbeginn eines bestimmten Dokumentfragments an. Sie wird mit dem Attribut repeatDur angegeben. Ihre Syntax ähnelt der eines Uhrzeitwerts, ist aber statt relativ zu einem anderen Animationsereignis oder einem Interaktionsereignis relativ zum Dokumentbeginn.
Zum Beispiel stoppt der folgende Schnipsel die Wiederholung der Animation 1 Minute und 30 Sekunden nach dem Dokumentbeginn
<animate
xlink:href="#orange-circle"
attributename="cx"
from="50"
to="450"
dur="2s"
begin="0s"
repeatcount="indefinite"
repeatdur="01:30"
fill="freeze"
id="circ-anim">
</animate>
Und hier ist die Live-Demo
Animationen synchronisieren basierend auf der Anzahl der Wiederholungen
Nun gehen wir einen Schritt zurück zum Thema der Synchronisierung zwischen zwei Animationen. Tatsächlich können Sie in SMIL Animationen so synchronisieren, dass eine Animation basierend auf der Anzahl der Wiederholungen einer anderen startet, plus oder minus einer eventuell hinzuzufügenden Zeitspanne.
Das folgende Beispiel startet die Animation des Rechtecks bei der zweiten Wiederholung der Kreisanimation
<animate
xlink:href="#blue-rectangle"
attributename="x"
from="50"
to="425"
dur="5s"
begin="circ-anim.repeat(2)"
fill="freeze"
id="rect-anim">
</animate>
Das Folgende ist eine Live-Demo, bei der die Rechteckanimation 2 Sekunden nach der zweiten Wiederholung der Kreisanimation startet.
Und hier ist ein Beispiel, das David Eisenberg für SVG Essentials (2nd Edition) zusammengestellt hat.
Steuerung von Animations-Keyframe-Werten: keyTimes und values
In CSS können wir die Werte angeben, die unsere animierte Eigenschaft in einem bestimmten Frame während der Animation annehmen soll. Wenn Sie beispielsweise den linken Versatz eines Elements animieren, anstatt ihn direkt von, sagen wir, 0 auf 300 zu animieren, können Sie ihn so animieren, dass er bestimmte Werte in bestimmten Frames annimmt, wie folgt
@keyframes example {
0% {
left: 0;
}
50% {
left: 320px;
}
80% {
left: 270px;
}
100% {
left: 300px;
}
}
Die Werte 0%, 20%, 80% und 100% sind die Frames der Animation, und die Werte in jedem Frame-Block sind die Werte für jeden Frame. Der oben beschriebene Effekt ist der eines Elements, das von einer Wand abprallt und dann in die Endposition zurückkehrt.
In SMIL können Sie die Werte pro Frame auf ähnliche Weise steuern, aber die Syntax ist ziemlich unterschiedlich.
Um die Keyframes anzugeben, verwenden Sie das Attribut keyTimes. Und um den Wert der animierten Eigenschaft für jeden Frame anzugeben, verwenden Sie das Attribut values. Die Namenskonventionen in SMIL sind ziemlich praktisch.
Wenn wir zu unserem bewegten Kreis zurückkehren und Werte verwenden, die denen in den oben genannten CSS-Keyframes ähneln, sieht der Code wie folgt aus
<animate
xlink:href="#orange-circle"
attributename="cx"
from="50"
to="450"
dur="2s"
begin="click"
values="50; 490; 350; 450"
keytimes="0; 0.5; 0.8; 1"
fill="freeze"
id="circ-anim">
</animate>
Was haben wir da gemacht?
Das erste, was hier auffällt, ist, dass die Keyframe-Zeiten und Zwischenwerte als Listen angegeben sind. Das Attribut keyTimes ist eine semikolon-getrennte Liste von Zeitwerten, die zur Steuerung des Tempos der Animation verwendet werden. Jede Zeit in der Liste entspricht einem Wert in der Liste des values-Attributs und definiert, wann der Wert in der Animationsfunktion verwendet wird. Jeder Zeitwert in der keyTimes-Liste wird als Gleitkommazahl zwischen 0 und 1 (einschließlich) angegeben, die einen proportionalen Versatz in die einfache Dauer des Animationselements darstellt. Die Schlüsselzeiten ähneln also denen in CSS, außer dass Sie sie statt als Prozentsätze als Bruch angeben.
Das Folgende ist die Live-Demo für den obigen Code. Klicken Sie auf den Kreis, um die Animation zu starten.
Beachten Sie, dass, wenn eine Liste von Werten verwendet wird, die Animation die Werte während der Animation in der angegebenen Reihenfolge anwendet. Wenn eine Liste von values angegeben wird, werden alle Attributwerte from, to und by ignoriert.
An dieser Stelle sei auch erwähnt, dass Sie das Attribut values auch ohne das Attribut keyTimes verwenden können – die Werte werden dann automatisch gleichmäßig über die Zeit verteilt (für jeden calcMode-Wert außer paced (siehe nächsten Abschnitt)).
Kontrolle des Animationstempos mit benutzerdefiniertem Easing: calcMode und keySplines
Ich werde wieder einen CSS-SMIL-Vergleich anstellen, da die SMIL-Syntax und -Konzepte viel einfacher zu verstehen sind, wenn Sie bereits mit CSS-Animationen vertraut sind.
In CSS können Sie das standardmäßige, gleichmäßige Animationstempo ändern und eine benutzerdefinierte Easing-Funktion angeben, die die Animation steuert, indem Sie die Eigenschaft animation-timing-function verwenden. Die Timing-Funktion kann eines von mehreren vordefinierten Schlüsselwörtern oder eine kubische Bézier-Funktion sein. Letztere kann mit einem Tool wie diesem Tool von Lea Verou erstellt werden.
In SMIL wird das Animationstempo mit dem Attribut calcMode angegeben. Das standardmäßige Animationstempo ist linear für alle Animationselemente außer animateMotion (darauf gehen wir später im Artikel ein). Zusätzlich zum Wert linear können Sie den Wert auf discrete, paced oder spline setzen.
discretegibt an, dass die Animationsfunktion ohne jegliche Interpolation von einem Wert zum nächsten springt. Dies ähnelt der Funktionsteps()in CSS.pacedähneltlinear, ignoriert jedoch alle durchkeyTimesdefinierten Zwischenfortschrittszeiten. Es berechnet den Abstand zwischen aufeinanderfolgenden Werten und teilt die Zeit entsprechend auf. Wenn Ihre Werte alle in linearer Reihenfolge sind, werden Sie den Unterschied nicht bemerken. Aber wenn sie hin und her gehen oder wenn es Farben sind (die als dreidimensionale Vektorwerte behandelt werden), werden Sie die Zwischenwerte definitiv sehen. Hier ist eine Demo mit freundlicher Genehmigung von Amelia Bellamy-Royds, die den Unterschied zwischen den bisher genannten dreicalcMode-Werten zeigt.- Der vierte von
calcModeakzeptierte Wert istspline. Er interpoliert von einem Wert in dervalues-Liste zum nächsten gemäß einer Zeitfunktion, die durch eine kubische Bézier-Spline definiert ist. Die Punkte der Spline werden im AttributkeyTimesdefiniert, und die Kontrollpunkte für jedes Intervall werden im AttributkeySplinesdefiniert.
Sie haben wahrscheinlich das neue Attribut im letzten Satz bemerkt: das Attribut keySplines. Was bewirkt also das Attribut keySplines?
Wieder zu den CSS-Äquivalenten.
In CSS können Sie das Animationstempo innerhalb jedes Keyframes festlegen, anstatt ein einziges Animationstempo für die gesamte Animation anzugeben. Dies gibt Ihnen eine bessere Kontrolle darüber, wie jede Keyframe-Animation ablaufen soll. Ein Beispiel für die Verwendung dieser Funktion ist die Erstellung eines springenden Ball-Effekts. Die Keyframes dafür könnten so aussehen
@keyframes bounce {
0% {
top: 0;
animation-timing-function: ease-in;
}
15% {
top: 200px;
animation-timing-function: ease-out;
}
30% {
top: 70px;
animation-timing-function: ease-in;
}
45% {
top: 200px;
animation-timing-function: ease-out;
}
60% {
top: 120px;
animation-timing-function: ease-in;
}
75% {
top: 200px;
animation-timing-function: ease-out;
}
90% {
top: 170px;
animation-timing-function: ease-in;
}
100% {
top: 200px;
animation-timing-function: ease-out;
}
}
Anstelle von Keyword-Easing-Funktionen hätten wir die entsprechenden kubischen Bézier-Funktionen verwenden können
ease-in=cubic-bezier(0.47, 0, 0.745, 0.715)ease-out=cubic-bezier(0.39, 0.575, 0.565, 1)
Beginnen wir damit, die Schlüsselzeiten und die Liste der values für unseren orangefarbenen Kreis anzugeben, um den gleichen Springeffekt zu erzielen
<animate
xlink:href="#orange-circle"
attributename="cy"
from="50"
to="250"
dur="3s"
begin="click"
values="50; 250; 120;250; 170; 250; 210; 250"
keytimes="0; 0.15; 0.3; 0.45; 0.6; 0.75; 0.9; 1"
fill="freeze"
id="circ-anim">
</animate>
Die Animation beginnt beim Klicken und friert ein, sobald sie den Endwert erreicht hat. Als Nächstes werden wir das Attribut keySplines hinzufügen, um das Tempo jedes Keyframes anzugeben.
Das Attribut keySplines nimmt eine Reihe von Bézier-Kontrollpunkten auf, die der keyTimes-Liste zugeordnet sind und eine kubische Bézier-Funktion definieren, die das Intervalltempo steuert. Der Attributwert ist eine semikolon-separierte Liste von Kontrollpunktbeschreibungen. Jede Kontrollpunktbeschreibung ist ein Satz von vier Werten: x1 y1 x2 y2, die die Bézier-Kontrollpunkte für ein Zeitsegment beschreiben. Die Werte müssen alle im Bereich von 0 bis 1 liegen, und das Attribut wird ignoriert, es sei denn, calcMode ist auf spline gesetzt.
Anstatt kubische Bézier-Funktionen als Werte zu akzeptieren, nimmt keySplines die Koordinaten der beiden Kontrollpunkte, die zum Zeichnen der Kurve verwendet werden. Die Kontrollpunkte sind im folgenden Screenshot aus Leas Tool zu sehen. Der Screenshot zeigt auch die Koordinaten jedes Punktes, jeweils mit der gleichen Farbe wie der Punkt selbst eingefärbt. Für das Attribut keySplines sind es diese Werte, die wir verwenden werden, um das Tempo der Keyframe-Animationen zu definieren.
SMIL erlaubt, dass diese Werte entweder durch Kommas mit optionalen Leerzeichen oder durch Leerzeichen allein getrennt werden. Die keyTimes-Werte, die das zugehörige Segment definieren, sind die Bézier-„Ankerpunkte“, und die keySplines-Werte sind die Kontrollpunkte. Somit muss es eine weniger Anzahl an Kontrollpunktgruppen geben als keyTimes-Werte.

Wenn wir zum Beispiel des springenden Balls zurückkehren, sind die Kontrollpunktkoordinaten für die ease-in- und ease-out-Funktionen in den folgenden Bildern dargestellt


Um dies in das SVG-Animationselement zu übersetzen, erhalten wir den folgenden Code
<animate
xlink:href="#orange-circle"
attributename="cy"
from="50"
to="250"
dur="3s"
begin="click"
values="50; 250; 120;250; 170; 250; 210; 250"
keytimes="0; 0.15; 0.3; 0.45; 0.6; 0.75; 0.9; 1"
keysplines="
.42 0 1 1;
0 0 .59 1;
.42 0 1 1;
0 0 .59 1;
.42 0 1 1;
0 0 .59 1;
.42 0 1 1;
0 0 .59 1;"
fill="freeze"
id="circ-anim">
</animate>
Hier ist die Live-Demo
Wenn Sie nur eine allgemeine Easing-Funktion für die gesamte Animation ohne Zwischenwerte angeben möchten, müssten Sie die Keyframes weiterhin mit dem Attribut keyTimes angeben, aber Sie würden nur die Start- und End-Keyframes angeben, nämlich 0; 1, und keine Zwischen-values.
Additive & kumulative Animationen: additive und accumulate
Manchmal ist es nützlich, eine Animation zu definieren, die dort beginnt, wo die vorherige Animation endete; oder eine, die die kumulative Summe der vorherigen Animationen als Wert verwendet, um fortzufahren. Dafür bietet SVG zwei passend benannte Attribute: additive und accumulate.
Angenommen, Sie haben ein Element, dessen Breite Sie "wachsen" lassen möchten, oder eine Linie, deren Länge Sie erhöhen möchten, oder ein Element, das Sie Schritt für Schritt von einer Position zur anderen bewegen möchten, über separate Schritte. Diese Funktion ist besonders nützlich für wiederholte Animationen.
Genau wie bei jeder anderen Animation geben Sie die Werte from und to an. Wenn Sie jedoch additive auf sum setzen, ist jeder dieser Werte relativ zum ursprünglichen Wert des animierten Attributs.
Zurück zu unserem Kreis. Für unseren Kreis ist die Anfangsposition von cx 50. Wenn Sie from="0" to="100" setzen, ist die Null tatsächlich die ursprüngliche 50, und die 100 ist tatsächlich 50 + 100; mit anderen Worten, es ist praktisch so etwas wie "from="50" to="150"".
Dadurch erhalten wir folgendes Ergebnis
Das ist alles, was das Attribut additive tut. Es gibt lediglich an, ob die Werte from und to relativ zum aktuellen Wert sein sollen oder nicht. Das Attribut nimmt nur einen von zwei Werten an: sum und replace. Letzterer ist der Standardwert und bedeutet im Grunde, dass die Werte from und to die aktuellen/ursprünglichen Werte ersetzen, was möglicherweise einen merkwürdigen Sprung verursachen kann, bevor die Animation beginnt. (Versuchen Sie, im obigen Beispiel sum durch replace zu ersetzen, um einen besseren Vergleich zu erhalten.)
Was aber, wenn wir möchten, dass die Werte so addiert werden, dass die zweite Wiederholung vom Endwert der vorherigen beginnt? Hier kommt das Attribut accumulate ins Spiel.
Das Attribut accumulate steuert, ob die Animation kumulativ ist oder nicht. Der Standardwert ist none, was bedeutet, dass die Animation bei Wiederholung beispielsweise wieder von vorne beginnt. Sie können es jedoch auf sum setzen, was angibt, dass jede Wiederholung nach der ersten auf dem letzten Wert der vorherigen Iteration aufbaut.
Wenn wir also zur vorherigen Animation zurückkehren und accumulate="sum" angeben würden, würden wir das folgende bevorzugte Ergebnis erhalten
Beachten Sie, dass das Attribut accumulate ignoriert wird, wenn der Zielattributwert keine Addition unterstützt oder wenn das Animationselement nicht wiederholt wird. Es wird auch ignoriert, wenn die Animationsfunktion nur mit dem Attribut to angegeben wird.
Festlegen der Endzeit einer Animation mit end
Zusätzlich zum Festlegen des Beginns einer Animation können Sie auch deren Ende mit dem Attribut end festlegen. Zum Beispiel können Sie eine Animation so einstellen, dass sie unbegrenzt wiederholt wird und dann stoppt, wenn ein anderes Element zu animieren beginnt. Das Attribut end nimmt Werte an, die denen des begin-Wertes ähneln. Sie können absolute oder relative Zeitwerte/Offsets, Wiederholungswerte, Ereigniswerte usw. angeben.
Im folgenden Beispiel bewegt sich der orangefarbene Kreis langsam über einen Zeitraum von 30 Sekunden auf die andere Seite der Leinwand. Der grüne Kreis wird ebenfalls animiert, aber nur, wenn er angeklickt wird. Die Animation des orangefarbenen Kreises endet, wenn die Animation des grünen Kreises beginnt. Klicken Sie auf den grünen Kreis, um zu sehen, wie der orangefarbene stoppt
Dieselbe Art der Animationssynchronisation kann natürlich auch für zwei Animationen erreicht werden, die auf dasselbe Element angewendet werden. Angenommen, wir setzen die Farbe des Kreises so, dass sie unbegrenzt von einem Wert zum anderen animiert wird. Wenn das Element dann angeklickt wird, bewegt es sich auf die andere Seite. Wir werden es jetzt so einstellen, dass die Farbanimation stoppt, sobald das Element angeklickt und die Bewegungsanimation ausgelöst wird.
Animationsintervalle mit mehreren begin- und end-Werten definieren
Tatsächlich akzeptieren sowohl die Attribute begin als auch end eine Liste von semikolon-getrennten Werten. Jeder Wert im Attribut begin entspricht einem Wert im Attribut end und bildet so aktive und inaktive Animationsintervalle.
Man kann sich das so vorstellen, wie ein fahrendes Auto, bei dem die Reifen des Autos aktiv und dann für bestimmte Zeiträume inaktiv sind, je nachdem, ob sich das Auto bewegt oder nicht. Sie können sogar den animierten Auto-Effekt erzeugen, indem Sie zwei Animationen auf das Auto anwenden: eine, die das Auto übersetzt oder entlang eines Pfades bewegt, der auch eine additive und kumulative Animation ist, und eine weitere Animation, die die Reifen des Autos in Intervallen dreht, die mit der Übersetzung synchronisiert wären.
Ein Beispiel, das mehrere Start- und Endzeiten (d.h. Intervalle) angibt, ist die folgende Demo, bei der das Rechteck basierend auf den definierten Intervallen gedreht wird und sich entsprechend von aktiv zu inaktiv ändert. (Führen Sie die Demo erneut aus, wenn Sie die Animation verpassen.)
Beachten Sie, dass ich im obigen Beispiel das Element verwendet habe, um das Rechteck um seinen Mittelpunkt zu drehen. Wir werden dieses Element in einem der folgenden Abschnitte genauer behandeln.
Beachten Sie auch, dass selbst wenn Sie repeatCount auf indefinite setzen, es durch die end-Werte überschrieben wird und nicht unbegrenzt wiederholt wird.
Beschränkung der aktiven Dauer eines Elements mit min und max
So wie Sie die Wiederholungszeit einer Animation beschränken können, können Sie auch die aktive Dauer einer Animation beschränken. Die Attribute min und max geben den minimalen bzw. maximalen Wert der aktiven Dauer an. Sie bieten uns eine Möglichkeit, die Unter- und Obergrenze der aktiven Dauer des Elements zu steuern. Beide Attribute nehmen einen Uhrzeitwert als Wert an.
Für min gibt dies die Länge des Minimalwerts der aktiven Dauer an, gemessen in der aktiven Zeit des Elements. Der Wert muss größer oder gleich 0 sein, was der Standardwert ist und die aktive Dauer überhaupt nicht einschränkt.
Für max gibt der Uhrzeitwert die Länge des Maximalwerts der aktiven Dauer an, gemessen in der aktiven Zeit des Elements. Der Wert muss ebenfalls größer als 0 sein. Der Standardwert für max ist indefinite. Dies schränkt die aktive Dauer überhaupt nicht ein.
Wenn sowohl die Attribute min als auch max angegeben werden, muss der Wert von max größer oder gleich dem Wert von min sein. Wird diese Anforderung nicht erfüllt, werden beide Attribute ignoriert.
Aber was definiert die aktive Dauer eines Elements? Wir haben die Wiederholungsdauer bereits erwähnt, zusätzlich zur „einfachen Dauer“, die die Dauer der Animation ohne Wiederholung ist (angegeben mit dur). Wie arbeiten diese also zusammen? Was überschreibt was? Und was ist mit dem Attribut end, das die Animation überschreiben und einfach beenden würde?
Der Ablauf ist der, dass der Browser zuerst die aktive Dauer basierend auf den Werten dur, repeatCount, repeatDur und end berechnet. Dann vergleicht er die berechnete Dauer mit den angegebenen min- und max-Werten. Liegt das Ergebnis innerhalb der Grenzen, ist dieser erste berechnete Dauerwert korrekt und wird nicht geändert. Andernfalls können zwei Situationen auftreten
- Ist die erste berechnete Dauer größer als der
max-Wert, so wird die aktive Dauer des Elements gleich demmax-Wert definiert. - Ist die erste berechnete Dauer kleiner als der
min-Wert, so wird die aktive Dauer des Elements gleich demmin-Wert und das Verhalten des Elements ist wie folgt- Wenn die Wiederholungsdauer (oder die einfache Dauer, wenn das Element sich nicht wiederholt) des Elements größer als
minist, wird das Element normal für die (durchminbegrenzte) aktive Dauer abgespielt. - Andernfalls wird das Element normal für seine Wiederholungsdauer (oder einfache Dauer, wenn das Element sich nicht wiederholt) abgespielt und dann je nach Wert des
fill-Attributs eingefroren oder nicht angezeigt.
- Wenn die Wiederholungsdauer (oder die einfache Dauer, wenn das Element sich nicht wiederholt) des Elements größer als
Das führt uns zu der Frage, wie der Browser die aktive Dauer tatsächlich berechnet. Aus Gründen der Kürze werde ich hier nicht ins Detail gehen. Aber es gibt eine sehr umfassende Tabelle in der Spezifikation, die die verschiedenen Kombinationen der Attribute dur, repeatCount, repeatDur und end zeigt und dann angibt, wie die aktive Dauer basierend auf jeder Kombination sein wird. Sie können die Tabelle einsehen und mehr darüber erfahren in diesem Abschnitt der Spezifikation.
Schließlich, wenn ein Element so definiert ist, dass es vor seinem Elternteil beginnt (z.B. mit einem einfachen negativen Offset-Wert), wird die minimale Dauer ab der berechneten Startzeit gemessen und nicht ab der beobachteten Startzeit. Das bedeutet, dass der min-Wert möglicherweise keine beobachtbare Wirkung hat.
Beispiel: Pfade morphen
Eines der Attribute, die in SMIL (aber nicht in CSS) animiert werden können, ist das Attribut d (kurz für data) eines SVG-Elements. Das Attribut d enthält die Daten, die die Umrisse der gezeichneten Form definieren. Die Pfaddaten bestehen aus einer Reihe von Befehlen und Koordinaten, die dem Browser mitteilen, wo und wie Punkte, Bögen und Linien gezeichnet werden sollen, die den endgültigen Pfad bilden.
Das Animieren dieses Attributs ermöglicht es uns, SVG-Pfade zu morphen und Form-Tweening-Effekte zu erzeugen. Um jedoch Formen morphen zu können, müssen die Start-, End- und alle Zwischenpfadformen genau die gleiche Anzahl von Scheitelpunkten/Punkten haben und in derselben Reihenfolge erscheinen. Wenn die Anzahl der Scheitelpunkte nicht übereinstimmt, funktioniert die Animation nicht. Der Grund dafür ist, dass die Formänderung tatsächlich durch Verschieben der Scheitelpunkte und Interpolieren ihrer Positionen geschieht. Wenn also ein Scheitelpunkt fehlt oder nicht übereinstimmt, werden die Pfade nicht mehr interpoliert.
Um einen SVG-Pfad zu animieren, geben Sie d als attributeName an und setzen dann die from- und to-Werte, die die Start- und Endformen angeben. Sie können das Attribut values verwenden, um beliebige Zwischenwerte anzugeben, die die Form durchlaufen soll.
Der Kürze halber werde ich hier nicht ins Detail gehen, wie dies zu tun ist. Stattdessen können Sie diesen ausgezeichneten Artikel von Noah Blon lesen, in dem er erklärt, wie er eine Art Ladeanimation mit Form-Tweening erstellt hat. Die Live-Demo zu Noahs Artikel ist diese
Und hier ist ein weiteres Morphing-Beispiel von Felix Hornoiu
Sie können sogar die Werte eines Pfades morphen, der als Clipping-Maske verwendet wird! Ein Beispiel dazu von Heather Buchel
Animationen entlang beliebiger Pfade: Das Element
Das Element ist mein Lieblings-SMIL-Animationselement. Sie können es verwenden, um ein Element entlang eines Pfades zu bewegen. Sie geben den Bewegungspfad auf eine von zwei Arten an, die wir als Nächstes behandeln werden, und stellen dann das Element so ein, dass es sich entlang dieses Pfades bewegt.
Das Element akzeptiert die zuvor genannten Attribute, plus drei weitere: keyPoints, rotate und path. Außerdem gibt es einen Unterschied bezüglich des Attributs calcMode, wobei der Standardwert für paced ist, nicht linear.
Festlegen des Bewegungspfades mit dem Attribut path
Das Attribut path wird verwendet, um den Bewegungspfad anzugeben. Es wird im gleichen Format ausgedrückt und auf die gleiche Weise interpretiert wie das Attribut d des path-Elements. Der Effekt einer Bewegungspfad-Animation besteht darin, eine zusätzliche Transformationsmatrix auf die aktuelle Transformationsmatrix für das referenzierte Objekt anzuwenden, die eine Translation entlang der x- und y-Achsen des aktuellen Benutzerkoordinatensystems durch die über die Zeit berechneten X- und Y-Werte bewirkt. Mit anderen Worten, der angegebene Pfad wird relativ zur aktuellen Position des Elements berechnet, indem die Pfaddaten verwendet werden, um das Element auf die Pfadposition zu transformieren.
Für unseren Kreis werden wir ihn entlang eines Pfades animieren, der wie folgt aussieht

Der benötigte Code, damit der Kreis sich entlang dieses Pfades bewegt, ist
<animatemotion xlink:href="#circle" dur="1s" begin="click" fill="freeze" path="M0,0c3.2-3.4,18.4-0.6,23.4-0.6c5.7,0.1,10.8,0.9,16.3,2.3 c13.5,3.5,26.1,9.6,38.5,16.2c12.3,6.5,21.3,16.8,31.9,25.4c10.8,8.7,21,18.3,31.7,26.9c9.3,7.4,20.9,11.5,31.4,16.7
c13.7,6.8,26.8,9.7,41.8,9c21.4-1,40.8-3.7,61.3-10.4c10.9-3.5,18.9-11.3,28.5-17.8c5.4-3.7,10.4-6.7,14.8-11.5
c1.9-2.1,3.7-5.5,6.5-6.5"></animatemotion>
Es gibt eine Sache, auf die ich mich hier konzentrieren möchte: die Koordinaten in den Pfaddaten. Der Pfad beginnt mit einer Bewegung (M) zum Punkt mit den Koordinaten (0, 0), bevor er eine Kurve (c) zu einem anderen Punkt zeichnet. Es ist wichtig zu beachten, dass der Punkt (0, 0) tatsächlich die Position des Kreises ist, egal wo er sich befindet – nicht die obere linke Ecke des Koordinatensystems. Wie wir oben erwähnt haben, sind die Koordinaten im Attribut path relativ zur aktuellen Position des Elements!
Das Ergebnis des obigen Codes ist
Würde man den Pfad von einem anderen Punkt als (0, 0) beginnen, würde der Kreis abrupt um den im Startpunkt angegebenen Betrag springen. Angenommen, Sie zeichnen einen Pfad in Illustrator und exportieren diese Pfaddaten dann, um sie als Bewegungspfad zu verwenden (das habe ich das erste Mal getan); der exportierte Pfad könnte dann so aussehen
<path fill="none" stroke="#000000" stroke-miterlimit="10" d="M100.4,102.2c3.2-3.4,18.4-0.6,23.4-0.6c5.7,0.1,10.8,0.9,16.3,2.3
c13.5,3.5,26.1,9.6,38.5,16.2c12.3,6.5,21.3,16.8,31.9,25.4c10.8,8.7,21,18.3,31.7,26.9c9.3,7.4,20.9,11.5,31.4,16.7
c13.7,6.8,26.8,9.7,41.8,9c21.4-1,40.8-3.7,61.3-10.4c10.9-3.5,18.9-11.3,28.5-17.8c5.4-3.7,10.4-6.7,14.8-11.5
c1.9-2.1,3.7-5.5,6.5-6.5"></path>
Der Startpunkt des Pfades ist in diesem Fall (100.4, 102.2). Wenn wir diese Daten als Bewegungspfad verwenden würden, würde der Kreis um ca. 100 Einheiten nach rechts und ca. 102 Einheiten nach unten springen und dann die Bewegung entlang des Pfades relativ zur neuen Position beginnen. Achten Sie also darauf, dies zu berücksichtigen, wenn Sie den Bewegungspfad für Ihre Animation vorbereiten.
Falls verwendet, legen die Attribute from, by, to und values eine Form auf der aktuellen Zeichenfläche fest, die den Bewegungspfad darstellt.
Festlegen des Bewegungspfades mit dem Element
Es gibt noch eine weitere Möglichkeit, einen Bewegungspfad anzugeben. Anstatt das relative Attribut path zu verwenden, können Sie einen externen Pfad mit dem Element referenzieren. Das, ein Kind des Elements, würde dann den externen Pfad über das Attribut xlink:href referenzieren.
<animatemotion xlink:href="#circle" dur="1s" begin="click" fill="freeze">
<mpath xlink:href="#motionPath"></mpath>
</animatemotion>
Der Bewegungspfad kann überall im Dokument definiert werden; er kann sogar buchstäblich nur innerhalb eines Elements definiert und überhaupt nicht auf der Leinwand gerendert werden. Im nächsten Beispiel wird der Pfad gerendert, da Sie in den meisten Fällen den Pfad anzeigen möchten, entlang dessen sich das Element bewegt.
Beachten Sie, dass laut Spezifikation
Die verschiedenen (x, y)-Punkte der Form stellen eine ergänzende Transformationsmatrix für die CTM (Current Transformation Matrix) des referenzierten Objekts bereit, die eine Translation entlang der x- und y-Achsen des aktuellen Benutzerkoordinatensystems durch die über die Zeit berechneten (x,y)-Werte der Form bewirkt. Somit wird das referenzierte Objekt im Laufe der Zeit durch den Versatz des Bewegungspfads relativ zum Ursprung des aktuellen Benutzerkoordinatensystems verschoben. Die ergänzende Transformation wird zusätzlich zu allen Transformationen angewendet, die durch die
transform-Eigenschaft des Zielelements oder durch Animationen auf diesem Attribut aufgrund vonanimateTransform-Elementen auf dem Zielelement entstehen.
Wieder wird die Position des Kreises mit den Koordinaten der Pfaddaten „multipliziert“ oder „transformiert“.
Im nächsten Beispiel haben wir einen Pfad in der Mitte der Zeichenfläche. Der Kreis ist am Anfang des Pfades positioniert. Doch wenn der Bewegungspfad angewendet wird, beginnt der Kreis seine Bewegung nicht von seiner aktuellen Position. Eine bessere Erklärung finden Sie in der Demo. Klicken Sie auf den Kreis, um ihn zu animieren.
Sehen Sie, wie der Kreis der gleichen Form des Pfades folgt, aber an einer anderen Position? Dies liegt daran, dass die Position des Kreises durch die Werte der Pfaddaten transformiert wird.
Eine Möglichkeit, dies zu umgehen, besteht darin, den Kreis bei (0, 0) zu positionieren, so dass er bei der Transformation mit den Pfaddaten wie erwartet startet und sich fortbewegt.
Eine andere Möglichkeit besteht darin, eine Transformation anzuwenden, die die Koordinaten des Kreises „zurücksetzt“, so dass sie vor dem Anwenden des Pfades auf Null berechnet werden.
Die folgende ist eine modifizierte Version der obigen Demo, die einen geschlossenen Pfad verwendet und die Bewegungsanimation unbegrenzt wiederholt.
Überschreibungsregeln für <animatemotion></animatemotion>
Da es für animateMotion mehr als eine Möglichkeit gibt, dasselbe zu tun, ist es nur sinnvoll, Überschreibungsregeln zu haben, um festzulegen, welche Werte andere überschreiben.
Die Überschreibungsregeln für animateMotion sind wie folgt
- Hinsichtlich der Definition des Bewegungspfades überschreibt das
mpath-Element daspath-Attribut, dasvaluesüberschreibt, welchesfrom,byundtoüberschreibt. - Hinsichtlich der Bestimmung der Punkte, die den
keyTimes-Attributen entsprechen, überschreibt das AttributkeyPointsdas Attributpath, welches dievaluesüberschreibt, welche wiederumfrom,byundtoüberschreiben.
Festlegen der Elementausrichtung entlang eines Bewegungspfades mit rotate
In unserem vorherigen Beispiel war das Element, das wir entlang des Pfades animierten, zufällig ein Kreis. Aber was, wenn wir ein Element animieren, das eine bestimmte Ausrichtung hat, wie zum Beispiel ein Auto-Symbol? Das Auto-Symbol im folgenden Beispiel wurde von Freepik entworfen.
In diesem Beispiel habe ich den Kreis durch eine Gruppe mit der ID „car“ ersetzt, die das Element enthält, aus dem die Gruppe besteht. Um das oben erwähnte Problem mit der Bewegung entlang des Pfades zu vermeiden, habe ich dann eine Transformation auf das Auto angewendet, die es um einen bestimmten Betrag übersetzt, sodass die Anfangsposition bei (0, 0) landet. Die Werte innerhalb der Transformationen sind tatsächlich die Koordinaten des Punktes, an dem der erste Pfad des Autos zu zeichnen beginnt (direkt nach dem Befehl M).
Das Auto beginnt dann, sich entlang des Bewegungspfades zu bewegen. Aber... so sieht die Bewegung aus
Die Ausrichtung des Autos ist fest und ändert sich nicht, um der des Bewegungspfades zu entsprechen. Um dies zu ändern, werden wir das Attribut rotate verwenden.
Das Attribut rotate nimmt einen von drei Werten an
auto: Zeigt an, dass das Objekt im Laufe der Zeit um den Winkel der Richtung (d.h. den gerichteten Tangentenvektor) des Bewegungspfades gedreht wird.auto-reverse: Zeigt an, dass das Objekt im Laufe der Zeit um den Winkel der Richtung (d.h. den gerichteten Tangentenvektor) des Bewegungspfades plus 180 Grad gedreht wird.- eine Zahl: Zeigt an, dass auf das Zielelement eine konstante Rotations-Transformation angewendet wird, wobei der Rotationswinkel der angegebenen Gradzahl entspricht.
Um die Ausrichtung des Autos im obigen Beispiel zu korrigieren, beginnen wir damit, den Rotationswert auf auto zu setzen. Wir erhalten das folgende Ergebnis
Wenn Sie möchten, dass sich das Auto außerhalb des Pfades bewegt, behebt der Wert auto-reverse dies.
Das sieht besser aus, aber wir haben immer noch ein Problem: Das Auto sieht aus, als würde es rückwärts entlang des Pfades fahren! Um das zu ändern, müssten wir das Auto entlang seiner Y-Achse spiegeln. Dies kann durch Skalierung um einen Faktor von „-1“ entlang dieser Achse geschehen. Wenn wir also die Transformation auf die Gruppe mit der ID car anwenden, wird sich das Auto wie erwartet vorwärts bewegen. Die Skalierungstransformation wird einfach mit der vorherigen Translation, die wir zuvor angewendet haben, verkettet.
Und die finale Demo sieht so aus
Steuerung der Animationsdistanz entlang des Bewegungspfades mit keyPoints
Das keyPoints-Attribut bietet die Möglichkeit, den Fortschritt entlang des Bewegungspfades für jeden der angegebenen keyTimes-Werte festzulegen. Wenn angegeben, bewirkt keyPoints, dass keyTimes auf die Werte in keyPoints angewendet wird, anstatt auf die im values-Attributarray oder die im path-Attribut angegebenen Punkte.
keyPoints akzeptiert eine durch Semikolons getrennte Liste von Gleitkommawerten zwischen 0 und 1 und gibt an, wie weit sich das Objekt zu dem durch den entsprechenden keyTimes-Wert angegebenen Zeitpunkt entlang des Bewegungspfades bewegen soll. Die Abstandsberechnungen werden durch die Algorithmen des Browsers bestimmt. Jeder Fortschrittswert in der Liste entspricht einem Wert in der keyTimes-Attributliste. Wenn eine Liste von keyPoints angegeben ist, muss die Liste der keyPoints genau so viele Werte enthalten wie die Liste der keyTimes.
Eine wichtige Sache, die hier zu beachten ist, ist, den calcMode-Wert für keyPoints auf linear zu setzen, damit es funktioniert. Es sieht auch so aus, als ob es logischerweise mit "paced animation" funktionieren *sollte*, wenn sich Ihre Schlüsselpunkte hin und her bewegen, aber das tut es nicht.
Das Folgende ist ein Beispiel von Amelia Bellamy-Royds (deren CodePen-Profil Sie sich unbedingt ansehen sollten), das keyPoints verwendet, um das Verhalten eines Starts einer Bewegung entlang eines Pfades mit einem vordefinierten Offset zu imitieren, da wir diese Möglichkeit derzeit in SMIL standardmäßig nicht haben.
Text entlang eines beliebigen Pfades bewegen
Text entlang eines beliebigen Pfades zu bewegen unterscheidet sich vom Bewegen anderer SVG-Elemente entlang von Pfaden. Um Text zu animieren, müssen Sie das Element verwenden, nicht das Element.
Zuerst positionieren wir den Text entlang eines Pfades. Dies kann durch das Verschachteln eines Elements innerhalb des Elements erfolgen. Der Text, der entlang eines Pfades positioniert werden soll, wird innerhalb des Elements definiert, nicht als Kind des Elements.
Das textPath wird dann auf den eigentlichen Pfad verweisen, den wir verwenden möchten, genau wie in den vorherigen Beispielen. Der referenzierte Pfad kann entweder auf der Zeichenfläche gerendert oder innerhalb eines s definiert werden. Sehen Sie sich den Code in der folgenden Demo an.
Um den Text entlang dieses Pfades zu animieren, werden wir das Element verwenden, um das Attribut startOffset zu animieren.
Das Attribut startOffset repräsentiert den Versatz des Textes auf dem Pfad. 0 % ist der Anfang des Pfades; 100 % repräsentiert das Ende. Wenn der Versatz beispielsweise auf 50 % eingestellt ist, beginnt der Text auf halbem Weg entlang des Pfades. Ich denke, Sie können sehen, wohin das führt.
Durch die Animation des startOffset werden wir den Effekt erzeugen, dass sich Text entlang des Pfades bewegt. Sehen Sie sich den Code in der folgenden Demo an.
Transformationen animieren: Das <animatetransform></animatetransform>-Element
Das Element animiert ein Transformationsattribut an einem Zielelement und ermöglicht so Animationen zur Steuerung von Translation, Skalierung, Rotation und/oder Scherung. Es übernimmt die gleichen Attribute wie das Element, plus ein zusätzliches Attribut: type.
Das Attribut type wird verwendet, um den Typ der zu animierenden Transformation anzugeben. Es nimmt einen von fünf Werten an: translate, scale, rotate, skewX und skewY.
Die Attribute from, by und to nehmen einen Wert an, der mit derselben Syntax ausgedrückt wird, die für den angegebenen Transformationstyp verfügbar ist
- Für
type="translate"wird jeder einzelne Wert als<tx> [,<ty>]</ty></tx>ausgedrückt. - Für
type="scale"wird jeder einzelne Wert als<sx> [,<sy>]</sy></sx>ausgedrückt. - Für
type="rotate"wird jeder einzelne Wert als<rotate-angle> [<cx> <cy>]</cy></cx></rotate-angle>ausgedrückt. - Für
type="skewX"undtype="skewY"wird jeder einzelne Wert als<skew-angle></skew-angle>ausgedrückt.
Wenn Sie mit der Syntax für die SVG-transform-Attributfunktionen nicht vertraut sind, und aus Gründen der Kürze dieses Artikels, und weil die Syntaxdetails und Funktionsweise außerhalb des Rahmens dieses Artikels liegen, empfehle ich Ihnen, den Artikel zu lesen, den ich vor einiger Zeit darüber geschrieben habe, bevor Sie mit diesem Leitfaden fortfahren: "Understanding SVG Coordinate Systems and Transformations (Part 2): The transform Attribute".
Zurück zu einer früheren Demo, in der wir das rosa Rechteck mit dem <animatetransform></animatetransform>-Element rotiert haben. Der Code für die Rotation sieht wie folgt aus
<rect id="deepPink-rectangle" width="50" height="50" x="50" y="50" fill="deepPink">
<animatetransform
xlink:href="#deepPink-rectangle"
attributename="transform"
attributetype="XML"
type="rotate"
from="0 75 75"
to="360 75 75"
dur="2s"
begin="0s"
repeatcount="indefinite"
fill="freeze"
>
</rect>
Die Attribute from und to geben den Rotationswinkel (Start und Ende) und das Rotationszentrum an. In beiden Fällen bleibt das Rotationszentrum natürlich dasselbe. Wenn Sie das Zentrum nicht angeben, ist es die obere linke Ecke der SVG-Leinwand. Die Live-Demo für den obigen Code ist die folgende
Hier ist ein weiteres lustiges Beispiel mit einer einzelnen animateTransform von Gabriel
Eine einzelne Transformation zu animieren ist einfach, jedoch können die Dinge wirklich unübersichtlich und kompliziert werden, wenn mehrere Transformationen involviert sind, insbesondere weil eine animateTransform eine andere überschreiben kann, so dass man statt Effekte hinzuzufügen und zu verketten, am Ende das genaue Gegenteil erhält. Das, zusätzlich zu der Art und Weise, wie SVG-Koordinatensysteme und -Transformationen tatsächlich funktionieren (siehe den zuvor erwähnten Artikel zu diesem Thema). Die Beispiele sind vielfältig und außerhalb des Rahmens dieses Artikels. Für die Transformation von SVGs empfehle ich die Verwendung von CSS-Transformationen. Implementierungen arbeiten daran, letztere perfekt mit SVG zum Laufen zu bringen, so dass Sie SMIL möglicherweise nie mehr zum Animieren von Transformationen in SVG verwenden müssen.
Das <set></set>-Element
Das set-Element bietet eine einfache Möglichkeit, den Wert eines Attributs für eine angegebene Dauer festzulegen. Es unterstützt alle Attributtypen, einschließlich derer, die nicht sinnvoll interpoliert werden können, wie Zeichenketten- und boolesche Werte. Das set-Element ist nicht additiv. Die Attribute additive und accumulate sind nicht zulässig und werden ignoriert, wenn sie angegeben werden.
Da es dazu dient, ein Element auf einen bestimmten Wert zu einem bestimmten Zeitpunkt und für einen bestimmten Zeitraum zu setzen, akzeptiert es nicht alle Attribute, die für die vorherigen Animationselemente erwähnt wurden. Es hat zum Beispiel kein from- oder by-Attribut, da sich der Wert, der sich ändert, nicht progressiv über den Zeitraum ändert.
Für set können Sie das Zielelement, den Attributnamen und -typ, den to-Wert angeben, und das Timing der Animation kann mit begin, dur, end, min, max, restart, repeatCount, repeatDur und fill gesteuert werden.
Das Folgende ist ein Beispiel, das die Farbe des rotierenden Rechtecks auf Blau setzt, wenn es angeklickt wird. Die Farbe bleibt für eine Dauer von 3 Sekunden blau und kehrt dann zur Originalfarbe zurück. Jedes Mal, wenn das Rechteck angeklickt wird, wird die set-Animation ausgelöst und die Farbe für drei Sekunden geändert.
Elemente, Attribute und Eigenschaften, die animiert werden können
Nicht alle SVG-Attribute können animiert werden, und nicht alle davon, die animiert werden können, können mit allen Animationselementen animiert werden. Eine vollständige Liste aller animierbaren Attribute und eine Tabelle, die zeigt, welche davon von welchen Elementen animiert werden können, finden Sie in diesem Abschnitt der SVG-Animationsspezifikation.
Schlusswort
SMIL hat viel Potenzial, und ich habe kaum die Oberfläche angekratzt und nur die Grundlagen und technischen Details ihrer Funktionsweise in SVG berührt. Es können viele sehr beeindruckende Effekte erzielt werden, insbesondere solche, die das Morphen und Transformieren von Formen beinhalten. Der Himmel ist die Grenze. Werden Sie verrückt! Und vergessen Sie nicht, Ihre Kreationen mit der Community zu teilen; wir würden gerne sehen, was Sie so gemacht haben. Vielen Dank fürs Lesen!
Dieser Artikel wurde basierend auf dieser Diskussion in den Kommentaren unten aktualisiert. Danke für Ihren Beitrag, Amelia. =)
Wow, ich hatte keine Ahnung, dass SVG eine eingebaute Pfadinterpolation hat! Das ist super spannend. Danke für das Kompendium toller Informationen, Sara!
Toller Artikel! Ich <3 SVG
Danke!
Vielleicht hat Flash endlich seinen Zweck gefunden: SVG/SMIL Animationsgenerator :-)
Meinst du, mit Flash ist es möglich, SVG-Animationen zu generieren?
Wow!
SVG war für mich immer "Ja, damit kann man ein paar Formen erstellen...". Seit ich die SVG-Tutorials von Jakob Jenkov (http://tutorials.jenkov.com/svg/index.html) entdeckt habe, hat sich das definitiv geändert.
Dieser Artikel kommt auch auf meine Leseliste!
Das ist ziemlich cool!
Ich mag "single animateTransform by Gabriel"
Wowo schöne künstliche SVG schön. Wie man SVG lernt, welche Website
Ich erinnere mich an meine „Macromedia Flash“-Tage :p
Toller Überblick.
Einige Korrekturen, die hoffentlich integriert werden können, um dies zu einer dauerhaften Referenz zu machen
Sie vermischen hier zwei verschiedene Konzepte (obwohl die Spezifikationen auch nicht viel besser sind). CSS ist kein XML-Namespace, und Sie können
attributeNamenicht verwenden, um anzugeben, dass es sich um die CSS-Eigenschaft handelt, die Sie animieren (obwohl dies der Standard ist, wenn SieattributeTypenicht angeben). Mit "XML-Namespace" meinen die Spezifikationen zum Beispiel das xlink inxlink:href.Ich bin mir nicht sicher, ob es etwas Spezifisches am diskreten Modus gibt, obwohl es die Unterschiede sicherlich deutlicher macht. Allgemeiner gesagt, funktioniert
bygenauso wie die Angabe von sowohlfromals auchto. Die Dinge sind nur anders, wenn Sietoallein angeben, und nur wenn Sie additive Animationen durchführen (entweder eine sich akkumulierende wiederholte Animation oder mehrere additive Animationen derselben Eigenschaft); die ersten beiden Formen werden als kumulative Offsets interpretiert, abertowird als Endwert interpretiert, unabhängig vom Startwert.Javascript scheint überflüssig. Es ist einfach mit der Wertesyntax zu bewerkstelligen:
values="0;100;0"erstellt eine alternierende Animation zwischen 0 und 100. Denken Sie daran, dassdurnun die Dauer eines vollständigen Hin- und Her-Durchlaufs der Animation ist. Ich würde immer noch eine einfachere Möglichkeit bevorzugen, Wiederholungen abzuwechseln (wenn Ihre Werte komplexe Pfaddatenbefehle sind, ist es mühsam, alles wiederholen zu müssen), aber es ist machbar.Es ist etwas fehlerhaft, aber es funktioniert. Hier ist ein Beispiel, das David Eisenberg für SVG Essentials, 2nd Edition erstellt hat.
Erwähnenswert ist, dass man
valuesauch ohnekeyTimesverwenden kann. Die Werte werden automatisch gleichmäßig über die Zeit verteilt (für jeden calc-Modus außerpaced).pacedignoriertkeyTimes, überschreibt aber nichtvalues. Es berechnet den Abstand zwischen aufeinanderfolgenden Werten und teilt die Zeit entsprechend auf. Wenn Ihre Werte alle in einer linearen Reihenfolge sind, werden Sie den Unterschied nicht bemerken. Aber wenn sie hin und her gehen oder wenn es Farben sind (die als dreidimensionale Vektorwerte behandelt werden), werden Sie die Zwischenwerte definitiv sehen.http://codepen.io/AmeliaBR/pen/EzAju?editors=100
Das stimmt nicht; jeder der End-Trigger stoppt die Animation, unabhängig davon, wie sie begonnen hat. Wenn Sie beispielsweise
clickin die Liste der End-Trigger aufgenommen haben, stoppt ein Klick die aktuelle Animation (verhindert aber keine zukünftigen).Ich neige dazu, dies in die entgegengesetzte Richtung zu denken – der Pfad ist fest, aber es ist der (0,0)-Punkt des Koordinatensystems des Kreises, der sich entlang dessen bewegt, nicht unbedingt der Kreis selbst. Aber beides funktioniert.
Genauer gesagt, geben sie jeweils Koordinaten im
x,y-Format an (oder eine durch Semikolons getrennte Liste von Koordinatenpaaren fürvalues). Die Bewegung erfolgt in geraden Linien von einer Koordinate zur nächsten.keyPointsfunktioniert einwandfrei, aber Sie müssencalcMode="linear"einstellen. Es *sollte* logischerweise mit "paced animation" funktionieren, wenn Ihre Schlüsselpunkte sich hin und her bewegen, aber das tut es nicht. Siehe zum Beispielhttp://codepen.io/AmeliaBR/pen/ewvrC?editors=100
Das ist ein wirklich raffiniziertes Beispiel, das zwei verschiedene Pfadelemente verwendet, eines vor und eines hinter dem sich bewegenden Element, um einen animierten z-Index zu simulieren (den SVG derzeit nicht hat)!
Natürlich haben Sie es geschafft, einige Dinge zu entdecken, die ich an den Spezifikationen nicht bemerkt hatte. Ich hatte nicht darauf geachtet, dass man Uhrwerte als Start-/Endzeitversätze verwenden *sollte*, daher hatte ich mir keine Sorgen gemacht, dass es nicht funktionierte (sie funktionieren einwandfrei als eigenständige Werte). Ich hatte auch übersehen, dass die mit einem ereignisbasierten Start-/Endwert verbundene Objekt-ID optional war. Und obwohl ich
minundmaxkannte, glaube ich nicht, dass ich sie jemals verwendet habe. Und ich hatte nicht erkannt, dasskeyTimes(odercalcMode="linear"im Allgemeinen) bei einem " mit einem Pfad, aber ohnekeyPointsstattdessen die Scheitelpunkte des Pfades verwenden würde.@Amelia
Vielen Dank für Ihren Kommentar.
Ich sehe mich in dem Artikel keines dieser beiden Sätze sagen. :o Ich habe nie gesagt, dass CSS ein XML-Namespace ist, und ich habe gesagt, dass man
attributeTypeverwendet, um den Namespace anzugeben, nichtattributeName.Daumen hoch. Das kann sicherlich dem Artikel hinzugefügt werden, um einen weiteren Anwendungsfall für
byzu zeigen. Obwohl, wie ich im Artikel erwähnt habe, der Effekt vonbybei Verwendung von diskreter Schrittweise deutlicher wird, gab es dort technisch nichts Falsches.Dem stimme ich hier nicht zu, aber das ändert nichts an der Tatsache, dass SMIL in diesem Bereich mangelhaft ist. Das ist jedoch auch eine Anmerkung, die dem Artikel hinzugefügt werden sollte. Vielen Dank.
Das ist seltsam. Ich habe gerade eine Demo mit
repeat()ausprobiert, die ich beim Schreiben des Artikels ausprobiert hatte und die vorher nicht funktionierte, aber jetzt funktioniert sie! Ich werde in Kürze ein Beispiel hinzufügen (und auch auf das von Ihnen gezeigte Beispiel verlinken).Wird auch hinzugefügt.
Das ist ein Fehler meinerseits, Entschuldigung. Die Spezifikation besagt, dass es nur die
keyTimesüberschreibt. Mein Fehler. :) Werde es auch beheben.Es *ist* wahr. Ja, der
end-Trigger stoppt die Animation, und dies gilt auch für andere Anwendungsfälle, z.B. wenn Sie mehrere Wiederholungen haben, kann derend-Wert auch andere aktive Dauerzeiten überschreiben, aber ich bin aus Gründen der Kürze nicht auf spezifische Anwendungsfälle und Beispiele eingegangen. Der Satz im Artikel ist technisch immer noch wahr.Stimmt, ich hatte übersehen, dass es mit
calcMode="linear"funktioniert. Danke für den Hinweis.Übrigens, es soll keine Anleitung sein; nur eine Demo, um zu zeigen, was möglich ist.
Beachten Sie auch, dass SVG tatsächlich eine
z-index-Eigenschaft hat, die aber noch in keinem Browser implementiert ist. Sie ist Teil von SVG2.Vielen Dank für all Ihre Anmerkungen. Werde den Artikel entsprechend mit relevanten Anmerkungen aktualisieren.
Prost!
Danke Sara,
Um es noch einmal zu betonen, ich war nicht übergenau, um kritisch zu sein, sondern weil ich denke, dass dies eine großartige Ressource ist, die so klar wie möglich sein sollte.
Beim Verwenden mehrerer Werte für
beginundendwollte ich darauf hinaus, dass es sich nicht um *übereinstimmende* Listen von Start- und Endzeiten handelt, wie es beikeyTimes-Werten mitkeyPointsodervaluesder Fall ist. Ihr Beispiel hat sie sauber zugeordnet, aber das muss nicht sein. Sie könnten die Reihenfolge der Zeiten in einer der Listen umkehren, und die Animation würde gleich funktionieren. Oder Sie könnten viele Startzeiten haben, aber nur eine übersteuernde Endzeit oder ein Ereignis.Bei Gabriels Beispiel war ich nicht kritisch, als ich sagte, es sei hinterhältig. Wenn Internetkommentare den Tonfall enthalten könnten, wäre dieser Satz in der gleichen Weise gesagt worden wie "Wow, großartig!". Das heißt, ich musste den Code sehr sorgfältig betrachten, um herauszufinden, wie er funktionierte. Und ich warte auch sehnsüchtig auf den z-Index in SVG2.
@Chris Coyier Ich habe einen wirklich langen Kommentar gepostet, der einige Fehler/zweideutige Aussagen im Artikel zusammenfasst, aber er wird nicht angezeigt. Wenn er nur in der Spam-Quarantäne ist, weil er so übermäßig lang war, kein Problem. Wenn nicht, senden Sie mir eine Notiz und ich werde ihn erneut posten und/oder Ihnen direkt senden.
@Amelia BR
Vielen Dank für Ihren Kommentar (diesen und den, der nicht gepostet wurde). Im Artikel fehlt ein Abschnitt, das Originaldokument hat diesen Abschnitt beim Schreiben aus irgendeinem Grund nicht gespeichert – vielleicht ist das der Grund für die Mehrdeutigkeit? Ich bin mir nicht sicher. Ich werde diesen Abschnitt hinzufügen, und Sie können mir die Liste auch gerne direkt zusenden @ [email protected]
Zum Experimentiertisch, das war erstaunlich aufschlussreich.
Wow, das war ein epischer Artikel, danke für all die Demos und Erklärungen, sehr gut gemacht.
Beste Grüße
Woow… Erstaunlicher Artikel… Ich liebe SVG…
Aber hier eine Frage: Wie arbeitet man mit Kollisionen?
D.h. wenn ich ein Spiel entwickle, das das Beispiel 'moving along path' als Basis verwendet, wie könnte ich wissen, wann das Auto ein Hindernis auf seinem Weg trifft?
In Javascript können Sie immer auf den aktuell animierten Wert eines SVG-Attributs zugreifen, innerhalb der
animVal-Unterproperty der relevanten Eigenschaft des Elementobjekts.Z.B. in diesem Pen animiere ich
cxeines Kreises und greife auf den aktuellen Wert als{element}.cx.animVal.value(in SVG-Benutzereinheiten, auch bekannt als px) oder{element}.cx.animVal.valueAsString(mit den ursprünglichen Einheiten, in diesem Fall Prozentsätzen) zu.http://codepen.io/AmeliaBR/pen/awvdB
Bei Bewegungen entlang eines Pfades wird es etwas komplizierter. Die Animation wird mit dem SVG-Attribut
transformangewendet. Die entsprechende Eigenschaft ist{element}.transform, vom Typ SVGAnimatedTransformList. Sie können die in diesem Link definierten DOM-Objekte, -Methoden und -Eigenschaften erkunden, um die Möglichkeiten der Verwendung des SVG-DOM zur Arbeit mit Transformationen zu entdecken.Wow…
@AmeliaBR: vielen Dank für die Mühe bei der Erklärung und das tolle, leicht verständliche Beispiel…
Ich werde mich dieses Wochenende an den DOM-Ansatz wagen…
@Amelia
Kein Problem, vielen Dank für Ihre konstruktiven Kommentare und Anmerkungen. Ich füge Ihre Anmerkungen gerne hinzu und korrigiere meine Fehler jederzeit. :)
Prost!
(P.S. Ja, schriftliche "Töne" können missverstanden werden, deshalb neige ich dazu, in meinen Kommentaren viele Smiley-Gesichter zu verwenden.)
((P.S.#2 Ihr SVG-Wissen ist beeindruckend! Ich habe einmal Ihren Artikel über die Verwendung von CSS-Variablen zum Stylen des Inhalts eines " Elements geteilt. Gutes Zeug! :))
Was ist mit Pfaden?!
Wie zeichne ich einen Pfad in SVG?! .. von A ……………………… nach B )
Wow! Gerade neu bei SVG und gerade gefunden. Lohnenswert....
Wow, diese kurz gezeigten Beispiele sind spannend. Ich freue mich darauf, diesen ganzen Artikel so schnell wie möglich zu lesen. Großartig!
Sehr interessanter Artikel. Aber ich liebe es, so etwas mit Canvas und JS zu machen.
Zuerst vielen Dank, Sara, für diesen wirklich epischen Leitfaden zu SVG-Animationen!
Dennoch möchte ich das Verhalten der Funktion
repeat(n)näher beleuchten. Ich habe festgestellt, dass es in Davids Beispiel, das Sie dem Artikel hinzugefügt haben, funktionierte (in Chrome 38+), aber leider konnte ich es in Ihrem Live-Beispiel im Artikel nicht zum Laufen bringen. Also habe ich ein bisschen damit herumgespielt und herausgefunden, dass es nur funktioniert, wenn beide folgenden Bedingungen wahr sind:1. Die
IDder referenzierten Animation enthält keinen Bindestrich (-);2. n in dem
repeat(n)der referenzierenden Animation ist kleiner alsrepeatCountder referenzierten Animation.Wenn eine davon falsch ist, funktioniert
repeat(n)nicht mehr.Das Erste erscheint mir besonders seltsam, da der Bindestrich (
-) meines Wissens nach für XML-IDs gültig ist. Bedeuten die Parsing-Regeln der Attributebeginundendzusätzliche Einschränkungen, vielleicht weil-auch als Minus für einen Zeitwert interpretiert werden kann? Oder ist es nur ein Chrome-Bug?Für die letztere Bedingung ist meine intuitive Erklärung, dass das
repeat(n)-Ereignis nicht ausgelöst wird, nachdem die gesamte Animation beendet ist (d.h. wenn eine Animation 2 Wiederholungen hat, wird nach der zweiten Wiederholung zuerst dasend-Ereignis ausgelöst und verhindert, dass dasrepeat(2)-Ereignis ausgelöst wird). Leider konnte ich weder einen Beweis noch einen Widerruf für meine Hypothese in der Spezifikation finden. Liege ich mit meiner Vermutung falsch?@SelenIT
Vielen Dank für Ihre Anmerkungen!
Ich bin auf den ersten Punkt mit dem Bindestrich gestoßen. Ich erinnere mich nicht, ob ich jemanden danach gefragt habe, und ich glaube nicht, dass ich einen Fehlerbericht eingereicht habe, weil ich nicht sicher bin, ob es sich tatsächlich um einen Fehler handelt oder nicht; vielen Dank, dass Sie ihn hier erwähnen.
Der zweite Punkt ist in der Tat interessant und macht perfekt Sinn, wenn man bedenkt, dass die Anzahl der Wiederholungen kleiner sein sollte als
repeatCount— warum sollte man eine dritte Wiederholung referenzieren, wenn die Animation nur zweimal wiederholt wird, richtig? Und es macht auch Sinn, wie Sie es ausdrücken: Ich denke, einend-Ereignis könnte auch der Grund dafür sein.Ich stelle es mir so vor, dass jede Wiederholung als
begin"registriert" wird. Das macht hier keinen Sinn, aber ich kann es nicht anders ausdrücken.Nochmals vielen Dank für Ihre wertvollen Anmerkungen. :)
Prost!
Das war ein fantastisches Tutorial, Sara. Innerhalb von 30 Minuten war ich mit meiner eigenen Animation, die ich auf der Website verwenden möchte, startklar. Wenn du noch da bist, habe ich mich etwas Einfaches gefragt.
Ich habe eine Shape-Tween-Animation. Sie funktioniert im Browser hin und her mit der animate-Eigenschaft.
Gibt es eine Möglichkeit, dies rein mit CSS oder mit Javascript zu tun? Ich möchte dies als Statuswechsel-Animation verwenden. Ich habe eine Form, die ein Ladebild ist, und dann möchte ich sie zu einem Play-Button tweenen, wenn sie bereit ist. Ich würde mich über eine Anleitung freuen. Danke!
Sara, vielen Dank für ein so großartiges SMIL-Tutorial mit tollen Beispielen! Ich muss jedoch meine zwei Cents hinzufügen. Als ich eine erste Version von SVG Circus erstellte, stieß ich auf einige Cross-Browser-Probleme bei "move-on-path"-Animationen mit
calcMode=splineundkeyTimes/keySplines, die Arrays von Werten enthielten. Das macht es schwierig, eine nicht-lineare, geloopte Animation zu erstellen, bei der beispielsweise eine Verzögerung auf fünf Schleifen angewendet wird. Aus diesem Grund beschloss ich, SMIL nicht mehr zu verwenden, schrieb eine benutzerdefinierte SVG-Animations-Engine in Javascript (RAF-basiert) und verschob SVG Circus darauf. Ich habe sie gestern quelloffen gemacht, Sie sind also herzlich eingeladen, damit zu experimentieren :)Können Sie bitte noch einmal mit weiteren Beispielen erklären
keyTimes und keySplines und wie sie zusammenhängen