Alles über SVG-Animationen

In diesem Artikel möchte ich die Feinheiten der Arbeit mit SVG-Grafiken, SVG-Animationen (einschließlich Pfad), Probleme und Methoden zu deren Lösung sowie verschiedene Fallstricke hervorheben, von denen es viele SVGs gibt. Ich positioniere diesen Artikel als detaillierte Anleitung.



Es wird keine Plugins, Bibliotheken usw. geben, wir werden nur über reines SVG sprechen.
Das einzige Tool, das ich verwenden werde, ist Adobe Illustrator.

Vorwort


Alles begann mit einem langweiligen Vortrag und in der Hoffnung, mich zumindest mit etwas zu unterhalten, beschloss ich, SVG-Grafiken zu studieren, nämlich Animation. Zu meiner Überraschung gab es im Internet nur sehr wenige Informationen. Überall gab es doppelte Informationen, die die Grundlagen erklärten, aber über Animation im Allgemeinen aus 2-3 Links mit absolut identischen Informationen. Dies ist eine Übersetzung des Artikels Ein Leitfaden für SVG-Animationen (SMIL) von Sarah Suydan.

Ihr Artikel spricht über alles, aber oberflächlich. Trotzdem empfehle ich Ihnen dringend, sich damit vertraut zu machen. * Link zur Übersetzung *

In den nächsten Wochen sammelte ich Stück für Stück Informationen aus verschiedenen Quellen. Das Ergebnis dieser Suche ist dieser Artikel.

Richtiger SVG-Export aus Illustrator


Dieser Abschnitt konzentriert sich auf die Funktionen und Probleme von Adobe Illustrator. Wenn Sie Illustrator nicht verwenden, können Sie diesen Teil überspringen.

Das Vorbereiten eines Dokuments für die Animation ist eine sehr wichtige Phase, deren Vernachlässigung zu sehr unangenehmen Konsequenzen führen kann. Um Ihnen beizubringen, wie Sie in Illustrator besser zeichnen können, werde ich dies nicht tun. Das einzige, was ich sagen werde, ist, dass Sie beim Zeichnen von Formen den Werten folgen sollten. Es ist wünschenswert, dass sie nur eine Zahl nach dem Dezimalpunkt haben, und es ist besser, eine Ganzzahl zu sein. Das Befolgen dieser Regel ist nicht erforderlich, verringert jedoch die Dateigröße, vereinfacht die weitere Animation und reduziert die Informationsmenge visuell. Schau mal rein

<path d="M 17.7 29 C 28.2 12.9 47 5.6 62.8 10.4 c 28.2 8.5 30 50.5 24.8 53.1 c -2.6 1.3 -10.4 -6.1 -29.2 -34.6"/> <path d="M 17.651 28.956 c 10.56 -16.04 29.351 -23.359 45.12 -18.589 c 28.151 8.516 29.957 50.5 24.841 53.063 c -2.631 1.318 -10.381 -6.148 -29.235 -34.643"/> 

Im Beispiel dieselbe Kurve, aber im ersten Fall eine Ziffer nach dem Dezimalpunkt und in den zweiten drei. Diese Kurve hat nur 4 Punkte und das zweite Beispiel ist ein Drittel länger als das erste. Stellen Sie sich vor, wie viel Platz eine 20-Punkte-Kurve benötigt.

Nachdem das Drahtmodell gezeichnet wurde, müssen Sie das Bild als SVG-Datei speichern. Es gibt zwei Möglichkeiten, dies zu tun: Speichern unter oder Exportieren unter. Aber welchen Weg soll man wählen? Wenn Sie mir vertrauen, verwenden Sie besser "Speichern unter". Wenn Sie wissen möchten, warum, setzen Sie einen Spoiler ein.

Warum also?
Auf den ersten Blick macht es keinen Unterschied, denn am Ende erhalten wir eine SVG-Datei mit unserem Bild. Die Unterschiede beginnen jedoch in der Phase der Exporteinstellungen.


Ich sehe keinen Grund darin, alle Parameter im Detail zu erklären. Illustrator macht das im Abschnitt "Beschreibung" sehr gut.

Wie Sie sehen können, hat "Speichern" mehr Einstellungen als "Exportieren", und für einige ist es ein guter Grund, den Export abzulehnen, aber wir werden fortfahren.

Wenn wir Dateien, die auf beide Arten gespeichert wurden, in einem Browser öffnen, werden wir den Unterschied nicht bemerken. Im Moment interessieren wir uns jedoch mehr nicht für das Aussehen, sondern für die Füllung, also werden wir dasselbe tun, aber über einen Texteditor. Hier werden die Unterschiede deutlicher. Ich schlage vor, dass Sie selbst schauen und Schlussfolgerungen ziehen. Ich habe nichts an den Dateien geändert. Ich habe nur das Ganze so kopiert, wie es ist.

Exportieren

 <svg id="_1" data-name=" 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 51 51"> <defs> <style> .cls-1 { fill: none; stroke: #4ec931; stroke-miterlimit: 10; } .cls-2 { fill: #4ec931; } .cls-3 { fill: #fff; } </style> </defs> <title>my_icon_E</title> <circle class="cls-1" cx="25.5" cy="25.5" r="20"/> <circle class="cls-1" cx="25.5" cy="25.5" r="25"/> <g id="_2" data-name=" 2"> <circle class="cls-2" cx="25.5" cy="25.5" r="15"/> <polygon class="cls-3" points="25.5 34.8 34 20.3 17 20.3 25.5 34.8"/> </g> </svg> 

Speichern

 <?xml version="1.0" encoding="utf-8"?> <!-- Generator: Adobe Illustrator 23.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <svg version="1.1" id="_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 100 100" style="enable-background:new 0 0 100 100;" xml:space="preserve"> <style type="text/css"> .st0{fill:none;stroke:#4EC931;stroke-miterlimit:10;} .st1{fill:#4EC931;} .st2{fill:#FFFFFF;} </style> <circle class="st0" cx="50" cy="50" r="20"/> <circle class="st0" cx="50" cy="50" r="25"/> <g id="_2"> <circle class="st1" cx="50" cy="50" r="15"/> <polygon class="st2" points="50,59.3 58.5,44.8 41.5,44.8 "/> </g> </svg> 

Zusätzlich zu den Unterschieden bei der Benennung von CSS-Klassen und dem Design im Allgemeinen, die einige als geschmackvoll erachten, gibt es andere Probleme. Beim "Exportieren" wurde das gesamte Bild um das Zweifache reduziert. Sie können dies anhand der Größe der Formen und des viewBox- Attributs beurteilen . Da es sich um eine Vektorgrafik handelt, wurde es nicht schlimmer, aber es ist immer noch unangenehm. "Speichern" hat die in Illustrator angegebenen Abmessungen beibehalten.

Aber all dies sind Blumen im Vergleich zu dem, was ein Schwein „exportieren“ kann. Insbesondere haben diese Beispiele dieses Problem nicht, wahrscheinlich weil das Bild sehr einfach ist. Beim Exportieren meiner anderen Arbeiten bin ich jedoch darauf gestoßen. Hier ist ihr Screenshot



Die Dateigröße ist groß genug, daher werde ich nur den Problemteil angeben

 <g id="-21" data-name=""> <path class="cls-9" d="M477.94,456.75a1.83,1.83,0,0,1-.9,1.36l-4.91,3.1a7.29,7.29,0,0,1-7.5,0l-16.29-9.72a1.85,1.85,0,0,1-.92-1.56v-3.68a1.85,1.85,0,0,0,.92,1.56l.38.23,15.91,9.49a7.29,7.29,0,0,0,7.5,0l4.53-2.86.38-.23a1.87,1.87,0,0,0,.9-1.36Z" transform="translate(-5.5 -5.5)"/> <path class="cls-10" d="M477,451.19l-16.38-9.5a7.28,7.28,0,0,0-7.32,0l-5,2.9a1.88,1.88,0,0,0-.94,1.51v.17a1.85,1.85,0,0,0,.92,1.56l.38.23,15.91,9.49a7.29,7.29,0,0,0,7.5,0l4.53-2.86.38-.23a1.87,1.87,0,0,0,.9-1.36v-.51A1.88,1.88,0,0,0,477,451.19Z" transform="translate(-5.5 -5.5)"/> </g> <g id="-22" data-name=""> <path class="cls-9" d="M525.37,557.86a1.85,1.85,0,0,1-.9,1.36l-33.22,19.64a7.29,7.29,0,0,1-7.5,0l-16.29-9.72a1.85,1.85,0,0,1-.92-1.56v-3.68a1.85,1.85,0,0,0,.92,1.56l.38.23,15.91,9.49a7.29,7.29,0,0,0,7.5,0l32.84-19.41.38-.23a1.83,1.83,0,0,0,.9-1.36Z" transform="translate(-5.5 -5.5)"/> <path class="cls-10" d="M524.45,552.3l-16.38-9.51a7.31,7.31,0,0,0-7.32,0l-33.27,19.44a1.89,1.89,0,0,0-.94,1.51v.17a1.85,1.85,0,0,0,.92,1.56l.38.23,15.91,9.49a7.29,7.29,0,0,0,7.5,0l32.84-19.41.38-.23a1.83,1.83,0,0,0,.9-1.36v-.5A1.86,1.86,0,0,0,524.45,552.3Z" transform="translate(-5.5 -5.5)"/> </g> 

Haben Sie etwas Ungewöhnliches bemerkt? Wenn Sie das Transformationsattribut schief betrachten, haben Sie Recht. Er ist es, der die ganze Himbeere verwöhnt. Wenn Sie ein Bild "exportieren", weist Illustrator es ALLEN <Pfad> -Elementen zu. Ein solches Problem wird jedoch bei der "Konservierung" nicht beobachtet.

Wenn Sie meine Empörung immer noch nicht verstehen, werde ich erklären: Wenn Sie die Bewegung eines solchen Elements animieren möchten, verschiebt es sich zur Seite. In diesem Fall 5,5 auf beiden Achsen. Dies liegt an der Tatsache, dass die Bewegungsanimation das Transformationsattribut ändert und alle vergangenen Werte zurücksetzt. Dies kann natürlich umgangen werden, aber es ist nicht besser, das Problem zu vermeiden, als seine Folgen später zu korrigieren ...

Im Moment habe ich nur dieses Problem bemerkt, aber das bedeutet nicht, dass es das einzige ist. Wenn Sie die Situation vernünftig einschätzen, stellt sich heraus, dass "Speichern unter" in allem gewinnt. Deshalb rate ich Ihnen, es zu verwenden.

Möglichkeiten zum Importieren eines SVG-Dokuments in HTML


Bevor ich direkt mit der Animation beginne, möchte ich darüber sprechen, wie SVG in eine Seite eingebettet wird. Jede Methode hat ihre eigenen „Funktionen“, die sich direkt auf die Animation auswirken. Und wenn Sie nicht darüber sprechen, ist der Artikel unvollständig.
Angenommen, Sie haben bereits eine vorgefertigte SVG mit interaktiver Animation und müssen dieses Dokument noch in die Site einbetten. Wie geht das?

Option Nummer eins ist, sich daran zu erinnern, dass SVG auch ein Bild ist und mit Standard-HTML-Tools importiert werden kann. Sie können ein <img> -Tag mit einem Link zu einem Dokument erstellen

 <img src="Hello_SVG.svg" /> 

Oder stellen Sie SVG als Hintergrundbild ein

 #box { background-image: url("Hello_again.svg"); } 

Der Hauptnachteil dieser Methode ist die Isolierung des Bildes. SVG als Ausstellung im Museum - Sie können sehen, keine Berührung. Die Animation im Inneren wird funktionieren, aber von Interaktivität kann keine Rede sein. Wenn beispielsweise eine Animation durch einen Benutzerklick ausgelöst wird oder der Inhalt eines SVG-Dokuments dynamisch geändert werden muss, ist diese Methode nicht für Sie geeignet.

Option Nummer zwei besteht darin, ein Objekt aus SVG mit den Tags <object> oder <embed> zu erstellen. Es ist auch möglich, <iframe> zum Erstellen eines Frames zu verwenden, ich empfehle jedoch nicht, diese Methode zu verwenden, da Für alle Browser ist eine Krücke erforderlich, damit diese Option korrekt angezeigt wird

 <object data="My_SVG.svg" type="image/svg+xml"></object> <embed src="My_SVG.svg" type="image/svg+xml" /> <iframe src="My_SVG.svg"></iframe> 

Hier ist es besser. Animationen erhalten die Möglichkeit, interaktiv zu sein, jedoch nur, wenn sie in einem SVG-Dokument deklariert sind und der Inhalt für externes JavaScript verfügbar ist. Trotzdem können <Objekt> und <iframe> einen Stub anzeigen, wenn das Bild plötzlich nicht mehr geladen wird.

Option Nummer drei besteht darin, den Inhalt des SVG-Dokuments einfach direkt in den HTML-Code einzufügen. Ja, das kannst du. Die SVG-Unterstützung wurde im HTML5-Standard angezeigt . Da SVG im Wesentlichen Teil der Seite selbst ist, ist der Zugriff überall möglich. Animationen und Stile von Elementen können sowohl innerhalb der SVG als auch in externen Dateien deklariert werden. Der Nachteil ist, dass solche Bilder nicht getrennt von der Seite zwischengespeichert werden

 <body> ... <svg> <!--  --> </svg> </body> 

SVG-Animation


Es gibt zwei Möglichkeiten, ein SVG-Element zu animieren:

  • CSS-Animation
  • In SVG integrierte SMIL-Animation (tatsächlich handelt es sich um eine SVG-Animation, die auf SMIL basiert und deren Funktionalität erweitert)

Persönlich trenne ich sie als Animationen von "extern" und "intern". Diese Aufteilung ist bedingt, weist aber dennoch funktionale Unterschiede auf. Wenn wir über die Unterschiede im Allgemeinen sprechen: CSS - hat eine bessere Unterstützung für Browser; SMIL - hat eine großartige Funktionalität. Es ist schwer zu sagen, welches besser zu verwenden ist, weil Sie sind sich sehr ähnlich. Die Auswahl hängt von der Aufgabe ab, daher möchte ich nur die Hauptgründe für die Verwendung von SMIL anstelle von CSS nennen

LÄCHELN - bei Bedarf:

  1. Was CSS nicht konnte (animieren eines nicht unterstützten Attributs usw.)
  2. Haben Sie eine genauere Kontrolle über die Animation.
  3. Path Morphing durchführen (Animation des Attributs d am Pfad- Tag)
  4. Animationen synchronisieren
  5. Machen Sie interaktive Animationen

Wenn ich geschrieben habe, dass SMIL für interaktive Animationen verwendet werden soll, bedeutet dies nicht, dass dies mit CSS nicht möglich ist. Simply SMIL ist ein funktionaleres und ausgefeilteres Tool. Und deshalb sollte es nur bei Bedarf verwendet werden. Wenn die Animation einfach ist und auf CSS verzichtet werden kann, sollte dies erfolgen.

CSS-Animation


Hier gibt es nichts Neues. Wir können jedes SVG-Element auf dieselbe Weise animieren wie mit HTML. Alle Animationen werden mit @keyframes erstellt . Da CSS-Animation ein weiteres Thema ist, werde ich nicht näher auf diesen Punkt eingehen. Das Netzwerk ist voll von Dokumentation und Anleitungen zu diesem Thema. Alles, was dort beschrieben wird, gilt für SVG, aber ich werde nur einige Beispiele nennen.

Das SVG-Dokument verfügt über interne Stylesheets, sodass wir Animationen darin schreiben

 <svg> <style> <!--   --> </style> <!--   SVG  --> </svg> 

Das Animieren eines SVG-Attributs ist so einfach wie CSS-Attribute

 @keyframes reduce_radius { from { r: 10; } to { r: 3; } } @keyframes change_fill { 0% { fill: #49549E; } 75% { fill: #1bceb1; } 100% { fill: #1bce4f; } } 

Sie können Werte als Prozentsatz und von-bis- Konstrukt angeben

Dann müssen nur noch die erstellten Animationen auf das gewünschte Element angewendet werden

 .circle { animation: change_fill 1s, popup 2s; } 

Alles, was ich oben beschrieben habe, sind statische Animationen, es riecht dort nicht nach Interaktivität. Aber was ist, wenn Sie wirklich wollen? Nun, etwas kann immer noch interaktiv und in CSS erledigt werden. Zum Beispiel, wenn Sie den Übergang in Kombination mit der Schwebepseudoklasse verwenden

 .circle { fill: #49549E; transition: .3s; } .circle:hover { fill: #1bceb1; } 
Wenn Sie mit der Maus über ein Objekt fahren, ändert es 300 ms lang seine Farbe von blau nach blau

Animation von Attributen und ein kleines Stück Interaktivität - hier enden die Funktionen der CSS-Animation. Diese Funktionalität reicht jedoch aus, da bei den meisten Aufgaben bestimmte Attribute animiert werden müssen. Fast jedes SVG-Attribut kann animiert werden. Und wenn ich „fast jedes“ schreibe, meine ich, dass Sie SEHR Glück haben, wenn Sie ein zufälliges Attribut auswählen und es sich als nicht invariant herausstellt.

SMIL-Animation


Es ist sofort erwähnenswert, dass SMIL-Animationen so alt wie die Welt sind und aussterben. Die Browserunterstützung ist anständig, aber immer noch geringer als bei CSS-Animationen. Es gibt jedoch einen Grund, warum SMIL immer noch attraktiv ist - dies kann, weil CSS dies nicht kann.

Ich werde mehr über SMIL sprechen, weil es viele Fallstricke gibt, über die sie selten schreiben. Und dieses Thema ist weniger beliebt als CSS. Die Haupt-Tags für die Animation sind <animate> , <set> , <animateTransform> , <animateMotion> .

<animate>


Beginnen wir mit schwerer Artillerie. <animate> - wird zum Animieren eines Attributs verwendet und ist das Hauptwerkzeug. Die restlichen Tags sind hochspezialisiert, aber das Wichtigste zuerst.

Wie wende ich eine Animation auf ein Element an?

Es gibt zwei Möglichkeiten, das Element anzugeben, auf das die Animation angewendet wird.

  1. Fügen Sie das Tag in das Element ein. Mit dieser Methode können Sie die Animation in das Objekt einkapseln, wodurch das Lesen des Codes erleichtert wird

     <circle ...> <animate .../> </circle> 
    In diesem Fall wird die Animation auf das Kreiselement angewendet.
  2. Übergeben Sie den Link zum Artikel. Nützlich, wenn alle Animationen an einem Ort gesammelt werden sollen

     <svg xmlns:xlink="http://www.w3.org/1999/xlink"> <circle id="blue" .../> ... <animate xlink:href="#blue" .../> </svg> 
    Hier wird das Attribut xlink: href verwendet, in dem die ID des Elements angegeben wird, für das die Animation gelten soll. Damit diese Methode funktioniert, müssen Sie den xlink- Namespace definieren. Dies erfolgt im <svg> -Tag .

Bei SVG 2 ist das Attribut xlink: href veraltet. In der Spezifikation wird empfohlen, stattdessen href zu verwenden, für das kein xlink- Namespace erforderlich ist.

 <circle id="blue" .../> ... <animate href="#blue" .../> 

Aber hier ist nicht alles so reibungslos - href wird von Safari nicht unterstützt. Es stellt sich eine Pattsituation heraus, ein Attribut ist veraltet, das andere wird teilweise nicht unterstützt. Welche Methode zu verwenden ist, entscheidet jeder für sich.

Für diejenigen, die Ähnlichkeiten mit CSS-Selektoren festgestellt haben: Es tut mir leid, dass ich enttäuschen muss. Ich kann nicht nach Klassen auf Elemente zugreifen

 <circle class="blue_circle" .../> <animate href=".blue_circle" .../> 
Das funktioniert nicht!

Wie gebe ich ein Attribut für die Animation an?

Hierfür gibt es attributeName . Der Wert ist der Name des Attributs, das animiert werden soll.

 <circle r="25" ...> <animate attributeName="r" ... /> </circle> 
Durch Angabe von r in attributeName melden wir, dass der Radius des Kreises animiert wird

Was ist attributeType und warum brauchst du es nicht?

Weil er nutzlos ist
Theoretisch kann ein Moment auftreten, in dem die Attributnamen in CSS und XML übereinstimmen, was zu Problemen führen kann. Um diesen Konflikt zu lösen, müssen Sie explizit einen Namespace angeben. Es gibt zwei Möglichkeiten: Geben Sie ein Präfix an oder verwenden Sie attributeType . Beginnen wir mit dem Präfix.

Überall schreiben sie so etwas wie das Folgende:
Sie können ein XMLNS-Präfix für ein Attribut angeben, um dessen Namespace explizit anzugeben
Diese Methode wird nebenbei und ohne Beispiele erwähnt. Ich werde also die Traditionen nicht ändern. (Ich rate Ihnen, hier anzuhalten, Präfixe als Albtraum zu vergessen und zu attributeType zu gehen, ich habe Sie gewarnt)

"Ich bin ein Masochist"
Der Inhalt dieses Spoilers ist eher unterhaltsam und explorativ. Keine nützlichen Informationen, außer der Tatsache, dass Präfixe nicht funktionieren, werden Sie hier nicht herausfinden

Zuerst müssen Sie eine genauere Definition und, wie Sie wissen, die genauesten Definitionen in den Spezifikationen und Standards finden.

Eine kurze Anleitung, wie man das Leben aufgibt
  1. Wir öffnen die Spezifikation für SVG-Animationen für den 14. März 2019
  2. Im Abschnitt attributeName sehen wir, dass er den SMIL-Animationsstandard für (oh horror) 2001 erbt
  3. Lesen Sie die Definition von attributeName
  4. Gewinn!

Die Übersetzung der Definition lautet wie folgt:
„Definiert den Namen des Zielattributs. Das XMLNS-Präfix kann verwendet werden, um den XML-Namespace für ein Attribut anzugeben. Das Präfix wird im Bereich des Animationselements interpretiert. “
Hmm, einfacher ging es nicht. Was fällt einer Person ein, die XML nach dem Lesen einer solchen Definition nicht kennt? Richtig. Das gleiche wie ich.

Ich nahm es wörtlich und dachte, es sollte so aussehen

 <animate attributeName="xmlns:* *"/> 

Ich habe über diese Methode nachgedacht und sie sicher vergessen, bevor ich diesen Artikel geschrieben habe. Die Probleme begannen, als ich mich entschied, es in der Praxis zu testen. Ich denke, ich werde niemanden überraschen, wenn ich sage, dass dies nicht funktioniert. Nach mehreren Stunden erfolgloser Suche habe ich „xmlns-Präfix“ gegoogelt und zu meiner Überraschung festgestellt, dass xmlns nicht das Präfix selbst ist, sondern (konzentriert, es wird jetzt schwierig) das Namespace-Design mit Präfixen .

Es sieht wie folgt aus:

 <** xmlns:**="* url *" ...> 
Dann wurde mir klar, dass ich nichts verstanden habe ... ganz am Anfang ... und jetzt im Prinzip auch

Nach ein paar Stunden fand ich endlich, wonach ich in Namespaces in XML suchte. Hier ist ein Originalbeispiel:

 <x xmlns:n1="http://www.w3.org" xmlns="http://www.w3.org" > <good a="1" n1:a="2" /> </x> 

Aber weißt du was am lustigsten ist? Es funktioniert immer noch nicht. Obwohl alles nach dem Buch gemacht wird

 <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:n1="http://www.w3.org/2000/svg"> <circle id="www" n1:r="10" .../> <animate href="#www" attributeName="n1:r" .../> </svg> 

Es gibt keine Fehler und sollte es auch nicht sein, denn alles wird nach den Regeln gemacht, aber das Problem ist, dass wir einen Kreis ohne Radius bekommen. Das gleiche Ergebnis wird erzielt, wenn Sie das Attribut r einfach nicht schreiben.

Epilog : SVG ignoriert vorangestellte Attribute. Selbst wenn SMIL das Attribut wirklich mit einem Präfix animiert, wird das Ergebnis dieser Animation nicht angezeigt.
Zu meiner Verteidigung werde ich sagen, dass ich mich nur mit SVG befasst habe, nämlich mit seiner Animation, damit der XML-Guru die Fackeln und die Heugabel beiseite legt. Wenn Sie wissen, wie diese Methode funktioniert, freuen Sie sich über Kommentare

Um explizit anzugeben, zu was das animierte Attribut gehört, wird attributeType verwendet. Es werden 3 Werte benötigt: CSS , XML , Auto . Sofern attributeType nicht explizit angegeben ist, wird auto verwendet. In diesem Fall werden zuerst die CSS-Eigenschaften überprüft. Wenn keine Übereinstimmungen vorhanden sind, werden die Attribute des Zielelements überprüft. Im Beispiel geben wir an, dass wir genau die CSS-Eigenschaft animieren werden

 <animate attributeType="CSS" attributeName="opacity" .../> 

Mit attributeType können Sie einfach und ohne Krücken angeben, zu was das animierte Attribut gehört, und so das "Problem" lösen, das es noch nicht einmal gibt.

Unerwartet, richtig? Wie ich zu Beginn des Kapitels sagte - SMIL stirbt und dies liegt an der Tatsache, dass die Animation auf die Schienen von CSS übertragen wird. Die meisten doppelten Attribute sind absolut identisch miteinander, d.h. Es spielt keine Rolle, ob das CSS- oder SMIL-Attribut gehört - das Ergebnis ist das gleiche. In Kombination mit dem standardmäßigen automatischen Wert ist die explizite Definition von attributeType nicht mehr erforderlich.

Ein Moment interessanter Fakten: attributeType wird von SVG nicht unterstützt. Woher kam er dann? Er kam von SMIL Animation zu uns, auf dem die SVG-Animation basiert. Außerdem wird attributeType nach SVG 1.1 Second Edition entfernt. Alle Beweise hier

Wie bestimme ich Animationswerte?

Das Angeben eines Attributs für die Animation reicht nicht aus, Sie müssen seine Werte definieren. Hier kommen von , zu , durch , Werte .

Beginnen wir mit einem Paar, das immer zusammen ist: von und nach . Die Bedeutung ihrer Existenz ist offensichtlich, vom Anfang bis zum Ende

 <circle r="25" ...> <animate attributeName="r" from="10" to="45" .../> </circle> 
Das Ergebnis der Animation ist eine sanfte Änderung des Radius des Kreises von 10 auf 45

Obwohl ich sagte, dass sie immer zusammen sind , kann to auch verwendet werden, ohne explizit zu deklarieren. In diesem Fall übernimmt from den im Zielelement definierten Wert. Im obigen Beispiel beginnt die Animation bei 25.

Wenn Sie mehrere Werte angeben müssen, werden Werte verwendet. Die Werte werden mit einem Semikolon aufgelistet.

 <circle r="25" ...> <animate attributeName="r" values="15;50;25" .../> </circle> 
Der Radiuswert verringert sich auf 15, erhöht sich dann auf 50 und kehrt dann zu seiner ursprünglichen Position zurück.

Letzte Schlange von . Es ist ihm egal, wo und wo, alles, was ihn interessiert, ist, wie viel. Mit anderen Worten, anstelle von absoluten Werten arbeitet es mit relativen

 <circle r="25" ...> <animate attributeName="r" by="15" .../> </circle> 
Infolge der Animation erhöht sich der Radius um 15, dh 25 + 15 = 40

Eine Legende geht um die Weiten von Handbüchern, die " by können verwendet werden, um den Betrag anzugeben, um den Animationen voranschreiten sollen". Ich verstehe es so: Wenn von = 20 bis = 50 und gegeben durch = 10 , dann muss dieser Pfad durch "Springen" in 10 überwunden werden, d. H. 20, 30, 40, 50. Aber egal wie ich es mit und ohne versuchte, die Animation änderte sich kein bisschen. Außerdem habe ich in der Spezifikation keine Bestätigung gefunden. Es scheint nur ein Fehler zu sein.

Werte haben die höchste Priorität, dann von - bis , zuletzt bis . Die niedrigste Priorität von erklärt, warum eine „Legende“ im Prinzip nicht funktionieren kann. Durch Arbeiten in Verbindung mit from wird in diesem Fall from einfach die aktuelle Position des Elements überschrieben

 <circle cy="50" ...> <animate attributeName="cy" from="70" by="30" .../> </circle> 
Hier beginnt die Animation anstelle von 50 bei 70 und endet bei 100

Mehr zu relativen Animationen

Sie können festlegen, dass andere Attribute genauso funktionieren wie bei . Dies erfolgt mit dem additiven Attribut, das zwei Positionen hat - Ersetzen und Summen .Die erste ist die Standardeinstellung, daher interessieren wir uns für die zweite. Mit einem Summenwert werden alle Attribute zum aktuellen Wert des Zielelements addiert, d. H. Wenn Sie einen Radius von 20 mit den Werten form = 5 und = 15 animieren, beträgt die Animation 20 + 5 bis 20 + 15

 <circle r="20" ...> <animate attributeName="r" from="5" to="15" additive="sum" .../> </circle> 

Bei der Durchführung der Animation wird scharf auf Position 25 gesprungen, was nicht gut ist (es sei denn, dies ist natürlich beabsichtigt). Dies kann mit form = 0 vermieden werden , aber dann geht die Bedeutung der Verwendung von sum verloren , da der gleiche Effekt ohne additive Verwendung von by erzielt werden kann

 <animate attributeName="r" from="0" to="15" additive="sum" .../> <animate attributeName="r" by="15" .../> 
Für mich ist die zweite Methode viel verständlicher und praktischer.

Wo soll die Dauer der Animation angegeben werden?

Das letzte erforderliche Attribut bleibt übrig, um eine funktionierende Animation zu erstellen - und das ist dur . Der Attributwert bestimmt die Dauer der Animation, die sowohl in Sekunden als auch in Millisekunden angegeben werden kann

 <animate dur="0.5s" .../> <animate dur="500ms" .../> <animate dur="00:00:00.5" .../> 
In der letzten Zeile können Sie erraten, dass es noch etwas anderes gibt ...

Sie können die Werte auch in Minuten und sogar Stunden angeben

 <animate dur="1.2min" .../> <animate dur="0.02h" .../> 
Fuck weiß, warum zum Teufel haben Sie es geschafft, die Werte in Stunden anzugeben, aber ich gehe nicht auf die Angelegenheiten anderer Leute ein, wenn Sie möchten, bedeutet dies, warum ...
Für andere Attribute werden temporäre Werte in derselben Form festgelegt.

Was kann ich tun, um zu verhindern, dass die Animation zum Anfang zurückkehrt?

Das Füllattribut (verwechseln Sie dieses Attribut nicht mit seinem Namensvetter) ist für das Verhalten des Elements nach dem Ende der Animation verantwortlich. Es gibt zwei Möglichkeiten:

  • entfernen (Standardwert) - Sobald die Animation ihr Ende erreicht hat, werden alle Transformationen zurückgesetzt und das Element nimmt den Status wie vor der Animation an
  • Einfrieren - Das Element friert an der endgültigen Position der Animation ein

Ist es möglich, Animationen zu schleifen?

Die Antwort lautet ja. Zu diesem Zweck gibt das Attribut repeatCount einen unbestimmten Wert an . Das Attribut bestimmt die Anzahl der Wiederholungen der Animation und ist standardmäßig 1, Sie können jedoch eine beliebige Anzahl angeben

 <animate repeatCount="indefinite" .../> <animate repeatCount="3" .../> 
Der erste wird sich endlos wiederholen, der zweite wird dreimal funktionieren.

Jetzt machen mich endlose Animationen wütend. Kann ich sie nach einer Weile ausschalten?

Für solche nervigen Leute hat Dur wiederholt . Dieses Attribut stoppt die Animation nach einer bestimmten Zeit ab dem Start der Animation! Einfach ausgedrückt, repeatDur begrenzt die Dauer der Animation. Der Hauptunterschied zu repeatCount besteht darin, dass die Animation in der Mitte gestoppt werden kann

 <animate dur="2s" repeatCount="indefinite" repeatDur="3s" .../> 
Die Animation wird in der Mitte der zweiten Iteration unterbrochen.

Und was ist, wenn die Animation nicht sofort gestartet werden soll?

Dann wird für Sie, mein Freund, das Attribut begin bereitgestellt. Er ist dafür verantwortlich, wann die Animation beginnt. Dieses Attribut ist sehr nützlich, da es auch zum Synchronisieren mehrerer Animationen verwendet wird, aber dazu später mehr.

Wenn Sie die übliche Verzögerung beim Starten angeben müssen, schreiben wir, in welchem ​​Zeitraum die Animation nach dem Öffnen des Dokuments beginnen soll

 <animate begin="1.5s" .../> 
Die Wiedergabe beginnt nach 1,5 Sekunden.

Sie können auch einen negativen Wert angeben. Dann beginnt die Animation nicht von vorne, sondern an der Stelle, an der sie sich nach einem bestimmten Zeitraum befinden würde

 <animate begin="-2s" dur="4s" .../> 
Die Animation beginnt mit dem Öffnen des Dokuments, wird jedoch von der Mitte aus abgespielt.

Wir machen die Animationen interaktiv. Zu Beginn

des Werts können Sie das Ereignis angeben, bei dem die Animation beginnen soll, jedoch ohne das Präfix „Ein“. Wenn Sie beispielsweise eine Click-through-Animation erstellen möchten, schreiben wir anstelle von "onclick" einen Klick

 <circle ...> <animate begin="click" .../> </circle> 

Im obigen Beispiel beginnt die Animation, wenn Sie auf das Element klicken, auf das die Animation angewendet wird. Wenn Sie eine Animation für ein Ereignis von einem anderen Element aus starten möchten, müssen Sie dessen ID angeben

 <circle id="button" .../> ... <animate begin="button.click" .../> 

Sie können auch mehrere Bedingungen für den Start der Animation festlegen. Listen Sie sie dazu getrennt durch Semikolons auf.

 <animate begin="click; 0s" .../> 
Die Animation wird beim Laden des Dokuments und durch Klicken gestartet

. Nicht alle Ereignisse werden unterstützt, aber die meisten mausbezogenen Ereignisse funktionieren. Ich werde sie alle verfügbaren Ereignisse nicht auflisten Sie finden irgendwo hier . Auch hat niemand die Methode des wissenschaftlichen Stocherns abgesagt.

Die Animation wird neu gestartet, ohne das Ende zu erreichen. Wie kann ich das beheben?

Ich werde ein einfaches Beispiel geben. Hier beginnt die Animation mit einem Klick. Wenn der Benutzer immer noch nicht drückt, erfolgt der automatische Start in 3 Sekunden

 <animate begin="click; 3s" dur="7s" .../> 

Es gibt jedoch ein Problem: Wenn der Benutzer vor dem automatischen Timer drückt, wird die Animation nach Ablauf von 3 Sekunden neu gestartet und erreicht nie das Ende. Das Neustartattribut im Wert whenNotActive wird zur Rettung kommen . Insgesamt hat er drei davon

  • always
  • whenNotActive – ,
  • never

 <animate begin="click; 3s" dur="7s" restart="whenNotActive" .../> 
, ,



, , , , . , , id begin , end , repeat

 <animate id="pop" begin="click" .../> <animate begin="pop.begin" .../> <animate begin="pop.end" .../> 

Wenn bei den ersten beiden alles klar ist, dann ist bei Wiederholung nicht alles so offensichtlich. In den Klammern ist Wiederholungszahl geschrieben, nach dem Sie die Animation ausgeführt werden soll (diese Zahl kann nicht durch Wiederholung folgen)

 <animate id="flip" repeatCount="5" .../> <animate begin="flip.repeat(2)" .../> 
Animation starten nach zwei Wiederholungen, und nicht jeder 2 Wiederholungen

Eine weitere möglicheine VerzögerungBezug auf das Ereignis zu spezifizieren. Zum Beispiel, wenn ich die Animation 2 Sekunden nach dem Start einer anderenabspielen möchte

 <animate id="another" .../> <animate begin="another.begin + 2s" .../> 

Oder starten Sie die Animation eine Sekunde vor dem Ende einer anderen

 <animate begin="another.end - 1s" .../> 

Was kann noch anfangen ...
Ich wollte diesen Abschnitt nennen, aber es ist richtiger, ihn "Was sollte er können, aber nicht können?" Zu nennen. Für bereits mein Lieblings Spezifikationen haben beginnen noch zwei Werte zu sein, muss er nehmen. Der erste ist accessKey , der die Animation durch Drücken einer im Unicode-Format angegebenen Taste startet. Die zweite ist die Wanduhr , die den Start der Animation in Echtzeit bestimmt. Und dort können Sie nicht nur die Uhr, sondern auch den Monat und das Jahr im Allgemeinen als vollständigen Satz angeben.

Leider wollte keiner von ihnen arbeiten. Obwohl der Verlust nicht groß ist, weil die Notwendigkeit für sie immer noch zweifelhaft ist

 <animate begin="accessKey(\u0077)" .../> <animate begin="wallclock(2019-04-09T19:56:00.0Z);" .../> 
Ich weiß nicht, wo das Problem liegt, vielleicht unterstützt mein Browser sie nicht oder etwas anderes ...

Kann ich die Animation unterbrechen?

Dies kann mit dem Attribut end erfolgen . In seiner Verwendung ist es identisch zu beginnen , Sie können auch die Zeit, Ereignisse usw. angeben. Wie Sie sehen, ist dies nicht die erste (und nicht die letzte) Möglichkeit, die Animation zu unterbrechen, da es repeatDur gibt , in dem Sie auch die Dauer der Animation festlegen können.Sie können die Zeit auch direktam Ende angeben. Die besonderen Merkmale sind die Ereignisbindung und die Möglichkeit, eine Liste von Werten anzugeben.

Angenommen, wir haben ein Element, das einen Zustand der Ruhe und Aktivität aufweist. Die zweite wird beim Klicken aktiviert. Und wir wollen die Restanimation mit dem Beginn der Aktivität unterbrechen. Sie können eine ähnliche Idee wie diese implementieren

 <animate id="idle" end="action.begin" begin="0s" repeatCount="indefinite" .../> <animate id="action" begin="click" .../> 
Die Restanimation wird standardmäßig gestartet. Wenn Sie auf ein Element klicken, wird eine Aktivitätsanimation gestartet und die

Restanimation unterbrochen. Kombinieren der Attribute Ende und Anfang

Wie Sie bereits wissen, können sowohl Anfang als auch Ende eine Liste von Werten annehmen. Es ist jedoch immer noch nicht klar, wie sich die Animation verhält, wenn Sie in beiden Attributen eine Liste angeben. Und es wird sich in gewisser Weise als Wiederholung mit einer konfigurierbaren Dauer und Intervallen zwischen ihnen herausstellen ... ist es nicht klar? Ich werde jetzt alles erklären.

Das erste, was Sie wissen müssen, ist, dass die Anzahl der Werte in den Listen übereinstimmen muss. Jedes Paar von Werten des Beginn - Endedefiniert eine "Wiederholung". Und die Zeit zwischen dem Ende einer „Wiederholung“ und dem Beginn der nächsten bestimmt die Verzögerung. Ich nenne sie aus einem bestimmten Grund „Wiederholungen“. Die Animation wird nicht angehalten und fortgesetzt, sondern unterbrochen und beginnt von vorne. Es stellt sich heraus, dass wir die Dauer jeder Wiederholung separat anpassen und nach jeder Wiederholung unterschiedliche Verzögerungen einstellen können

 <animate dur="3s" begin="1s; 5s; 9s" end = "2s; 8s; 11s" .../> 
Im Beispiel hat die Animation 3 "Wiederholungen". Die erste beginnt eine Sekunde nach dem Laden des Dokuments und dauert nur eine von drei Sekunden. Dann eine Verzögerung von 3 Sekunden und danach eine vollständige Animation von 3 Sekunden. Wieder eine Verzögerung, aber in 1 Sekunde. Die letzte Wiederholung wird nach zwei Sekunden Animation

unterbrochen . Können Sie die Animation trotzdem irgendwie unterbrechen?
Ein paar nutzlose Attribute für das Sparschwein
Keeneeee, es gibt zwei weitere Attribute - min und max . Wie der Name schon sagt,definiert min das Minimum und max diemaximale Dauer. Zunächst wird die Animationsdauer anhand der Werte dur , repeatCount , repeatDur , berechnet .Ende . Danach wird die erhaltene Dauer an die durch min und max angegebenen Frames angepasst . Auf dem Papier ist alles schön, mal sehen, wie es in der Praxis funktioniert.

Mit max ist alles einfach, dies ist ein weiteres Attribut, das die Obergrenze definiert. Wenn die berechnete Dauer kleiner als max ist , wird sie ignoriert, und wenn sie länger ist, wird die Dauer der Animation gleich max

 <animate dur="10s" repeatDur="7s" end="5s" max="4s" .../> 
Es wird für 4 Sekunden unterbrochen,

aber min hatte weniger Glück. Wenn die berechnete Animationsdauer länger als min ist , wird sie ignoriert, was logisch ist. Wenn die berechnete Dauer jedoch weniger als min beträgt , wird sie manchmal ignoriert und manchmal nicht.
Warum warum ?! Dieser Moment ist sehr leicht zu verwirren, also lesen Sie ihn sorgfältig durch.

Wir haben zwei Möglichkeiten, wenn die berechnete Dauer weniger als min beträgt :

  1. Weil die Animation selbst vorbei ist, d.h. dur * repeatCount < min

     <animate dur="2s" repeatCount="2" min="5s" .../> 
    Bei dieser Option wird das min- Attribut einfach ignoriert. Die Animation wird in der vierten Sekunde gestoppt
  2. repeatDur end .

    • repeatDur , , min , min

       <animate dur="1s" repeatCount ="indefinite" repeatDur="3s" end="5s" min="4s" .../> 
      repeatDur , min , 3
    • repeatDur , end min , end , min

       <animate dur="1s" repeatCount ="indefinite" end="2s" min="4s" .../> 
      4 , .. min end

Aufgrund der Fülle von Attributen, die die Animation unterbrechen, herrscht große Verwirrung. Infolgedessen macht Max und Min keinen großen Sinn , da gut geschriebene Animationen sie nicht mehr benötigen.

Wie verwalte ich Keyframes und wo soll die Zeitfunktion angegeben werden?

Dazu müssen Sie die Attribute keyTimes , keySplines , calcMode kennen . Nachdem wir die Liste in Werten angegeben haben , deklarieren wir Schlüsselbilder, die jedoch gleichmäßig verteilt sind. Dank des Attributs keyTimesWir können den Übergang von einem Zustand in einen anderen beschleunigen oder verlangsamen. Darin werden auch in Form einer Liste die Werte für jeden Frame angegeben. Die Werte geben die Position des Keyframes auf der Zeitachse als Prozentsatz relativ zur Dauer der gesamten Animation an (0 - 0%; 0,5 - 50%; 1 - 100%).

Es gibt mehrere Regeln: Jeder Wert repräsentiert eine Gleitkommazahl von 0 bis 1, die Anzahl der Werte in den Listen muss übereinstimmen, der erste Wert muss 0 sein und die letzte 1, jeder nächste Wert muss größer als der vorherige sein. Ich denke, Sie verstehen, dass es keinen Sinn macht, keyTimes ohne Werte zu verwenden . Und jetzt ein Beispiel

 <animate values="15; 10; 45; 55; 50" keyTimes="0; 0.1; 0.6; 0.9; 1" .../> 

Standardmäßig erfolgen alle Konvertierungen linear. Um dies zu ändern, müssen Sie in calcMode einen anderen Modus angeben . Und es gibt nicht viele Möglichkeiten:

  • linear - Standardwert, keine Erklärung erforderlich
  • Tempo - Zeitintervalle werden so berechnet, dass die Geschwindigkeit zwischen Keyframes konstant ist
  • diskret - Animation wechselt in Sprüngen ohne Interpolation zwischen Keyframes
  • Spline - wir können sagen, dass dies ein manueller Steuermodus ist (dazu später)

Leider sind dies alles eingebaute Funktionen, hier finden Sie keine Leichtigkeit in \ out wie in CSS. Diese Bedürfnisse müssen also das Regime befriedigen, das ich "manuell" nannte.

Das am schwierigsten zu verstehende ist das Tempo , deshalb werde ich es genauer erklären. Sehen Sie sich zunächst an, wie die Animation im Standardmodus funktioniert. Die Animation dauert 2 Sekunden und wir haben 3 Keyframes - Initial, Intermediate, Final

 <animate dur="2s" values="100; 200; 150" .../> 

Wenn Sie sich die Animation ansehen, wird deutlich, dass in regelmäßigen Abständen zwischen Keyframes gewechselt wird. Der Abstand zwischen dem ersten und dem zweiten beträgt 100 und zwischen dem zweiten und dem dritten beträgt 50, d.h. die Hälfte des ersten Weges. Durch einfache Berechnungen wird klar, dass das Element das zweite Segment doppelt so langsam durchläuft wie das erste. Fügen Sie nun calcMode = "paced" hinzu und sehen Sie, was sich geändert hat.

 <animate dur="2s" values="100; 200; 150" calcMode="paced" .../> 

Und die Geschwindigkeit des Elements hat sich geändert. Jetzt ist es so konzipiert, dass es die gesamte Strecke mit der gleichen Geschwindigkeit zurücklegt. Mit anderen Worten, das Element bewegt beide Segmente gleichmäßig.

Schauen wir uns nun den Spline- Modus und das keySplines- Attribut an . Sie haben einige Ähnlichkeiten ... hmm ...


Wenn Spline einen manuellen Modus definiert , definiert das Attribut keySplines die Werte für diesen Modus. Offensichtlich funktioniert das eine nicht ohne das andere. Die Werte in keySplines werden durch eine Liste festgelegt, in der die Koordinaten von zwei Punkten für kubisches Bezier angegeben sind.

Mehr zur Bezier Cubic Function
Dies ist eine Funktion, die die Intensität der Bewegung bestimmt. Es besteht aus 4 Gleitkommazahlen von 0 bis 1 und sieht im Allgemeinen so aus: kubischer Bezier (x1, y1, x2, y2). Zahlenpaare sind Koordinaten und bilden zwei Punkte, die die Kurve definieren.

Sie können mehr über Cubic-Bezier im Internet lesen. Um einen kubischen Bezier zu bauen, empfehle ich Ihnen, Online-Dienste zu nutzen . Dort können Sie sich auch Beispiele ansehen und mit den Werten spielen.

Die Anzahl der Werte in keySplines sollte 1 kleiner als die Werte sein . Dies liegt daran, dass wir Werte nicht für Schlüsselbilder, sondern für Intervalle zwischen ihnen angeben.

 <animate values="100; 200; 150" keySplines=".25 .1 .25 1; 0 0 .58 1" calcMode="spline" .../> 
,

– , .
from - to by , : keyTimes "0; 1"

 <animate from="10" to="50" keyTimes="0; 1" keySplines=".25 .1 .25 1;" calcMode="spline" .../> 
Wird anstelle von - verwenden Werte aus den beiden Werten, dann wird dieses Problem nicht

wie Einsparungen von Animation zu realisieren?

Zunächst eine kleine Theorie - die nächste Wiederholung der kumulativen Animation wird dort fortgesetzt, wo die vorherige endete. Es wäre cool, aber nicht sehr ... Die Tatsache, dass kumulative Animationen nur innerhalb von Wiederholungen funktionieren, ist enttäuschend.

Nun erfahren Sie, wie Sie die Animation kumulativ machen: Sie müssen das Attribut akkumulieren (das standardmäßig keines ist) auf Summe setzen

 <animate by="100" repeatCount="3" accumulate="sum".../> 

Es sollte beachtet werden, dass sich alle Wiederholungen mit Ausnahme der ersten so verhalten, als ob additiv = "Summe" , wenn Sie Werte oder von - bis verwenden . Und akkumulieren wird ignoriert, wenn nur ein to angegeben ist . Wir verstehen das Verwandeln der Kontur Nachdem ich die Grundlagen erklärt habe, ist es Zeit, zu wirklich coolen und komplexen Dingen überzugehen. Ich bin sicher, dass jemand diesen Artikel nur für diesen Abschnitt geöffnet hat. Path Morphing ist eine Animation des Attributs d des Pfad- Tags , mit der Sie den Effekt einer reibungslosen Änderung der Formform erzielen können. Derzeit ist dies mit integrierten Tools nur mit SMIL möglich. In





values gibt die Liste der Werte für das d- Attribut an, durch die das Element geleitet wird. Sie können auch von - bis verwenden . Im Allgemeinen sieht der Umriss-Morph so aus

 <animate attributeName="d" values=" 1;  2; ..." .../> 

Kommen wir nun zu den Feinheiten dieses Prozesses:

Für diejenigen, die sich im Tank befinden, enthält das Attribut d eine Reihe von Punkten, die anschließend nacheinander zu einer Figur verbunden werden. Ein genauerer Blick zeigt, dass die Werteliste den Anweisungen für die CNC-Maschine (oder den „Roboter“ im Informatikunterricht) ähnelt. Es gibt viele Teams, einige sind dafür verantwortlich, den Cursor zu bewegen, andere für das Zeichnen, andere dafür, wie stark die Kurve die Linie sein wird usw. ( Alle Teams sind hier ).

Damit Morphing funktioniert, muss die Anzahl der Befehle übereinstimmen und vom gleichen Typ sein . Wenn Sie diese Bedingung ignorieren, erfolgt keine Interpolation - die Animation springt wie bei von einem Zustand in einen anderencalcMode = "diskret" . Auf den ersten Blick ist es nichts Kompliziertes. Dies ist der Fall, wenn Sie Formen ohne Kurven animieren. Wenn nicht, beginnen die Schwierigkeiten.

Bei der Erstellung komplexer Grafiken verwendet jeder Vektoreditoren und hat die Angewohnheit, den "Code" so weit wie möglich zu optimieren. Dies ist normalerweise ein Plus, aber in unserem Fall nicht. Am Ausgang haben wir möglicherweise eine Liste mit einer Länge, aber mit Teams unterschiedlicher Typen, und dies ist ein Verstoß gegen eine der Regeln. Ich habe Adobe Illustrator verwendet und keine Option gefunden, mit der Probleme behoben werden könnten. Manchmal fehlt dieses Problem nach dem Willen der Götter von Dizign. Im Ernst, die Wahrscheinlichkeit eines Problems ist direkt proportional zur Komplexität der Figur und des Morphings.

Derzeit ist die einzige Lösung für das Problem die Konvertierung des „krummen Codes“ in der Shape Shifter- Webanwendung . Dies ist die Option, die ich benutze. Mit Shape Shifter können Sie nicht nur fehlerhaften Code reparieren, sondern auch das Ergebnis anzeigen, Animationen eines anderen Typs hinzufügen und das Ergebnis in einem praktischen Format exportieren.

Als nächstes folgt eine Schritt-für-Schritt-Anleitung, in der ich Ihnen erklären werde, wie Sie eine so schöne Animation erstellen

Lehre mich!
: SVG Adobe Illustrator, , Shape Shifter . CSS, SMIL .

. Illustrator. , . 200x200 .

, , . , , «». ,

. . « »

, . , , ,

. , , . , . SVG , . …

. , . SVG . ( Illustrator )

, , Illustrator <path> , <circle> . , . , , . - ( SVGO ), . .

d , )

 <?xml version="1.0" encoding="utf-8"?> <!-- Generator: Adobe Illustrator 23.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 200 200" style="enable-background:new 0 0 200 200;" xml:space="preserve"> <style type="text/css"> .st0{fill:#D38911;} .st1{fill:#87872B;} .st2{fill:#CEB629;} .st3{fill:none;stroke:#DD913E;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:12,200;} </style> <g id="Pulse"> <g> <path class="st0" d="M100,87c44.1,0,80,35.9,80,80s-35.9,80-80,80s-80-35.9-80-80S55.9,87,100,87 M100,82c-46.9,0-85,38.1-85,85 s38.1,85,85,85s85-38.1,85-85S146.9,82,100,82L100,82z"/> </g> </g> <g id="_x3F__1_"> <path id="side" class="st1" d="   "/> <path id="front" class="st2" d="   "/> </g> <g id="Particles"> <line class="st3" x1="80" y1="162.9" x2="42" y2="59.1"/> <line class="st3" x1="90.1" y1="148.8" x2="59.8" y2="28.8"/> <line class="st3" x1="107.9" y1="155.6" x2="124.9" y2="15.9"/> <line class="st3" x1="94.4" y1="160.4" x2="154.3" y2="7.2"/> <line class="st3" x1="119.3" y1="157" x2="159.2" y2="75.5"/> <line class="st3" x1="98" y1="169" x2="87.7" y2="10.7"/> <line class="st3" x1="80.4" y1="147.6" x2="63.2" y2="14.1"/> </g> </svg> 

 <?xml version="1.0" encoding="utf-8"?> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200"> <style type="text/css"> #Pulse{fill: none; stroke: #D38911; stroke-width: 5;} #side{fill:#87872B;} #front{fill:#CEB629;} .particles{fill:none;stroke:#DD913E;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:12,200;} </style> <circle id="Pulse" cx="100" cy="167" r="85"/> <g id="Sign"> <path id="side" d="   "/> <path id="front" d="   "/> </g> <g id="Particles"> <line class="particles" x1="80" y1="162.9" x2="42" y2="59.1"/> <line class="particles" x1="90.1" y1="148.8" x2="59.8" y2="28.8"/> <line class="particles" x1="107.9" y1="155.6" x2="124.9" y2="15.9"/> <line class="particles" x1="94.4" y1="160.4" x2="154.3" y2="7.2"/> <line class="particles" x1="119.3" y1="157" x2="159.2" y2="75.5"/> <line class="particles" x1="98" y1="169" x2="87.7" y2="10.7"/> <line class="particles" x1="80.4" y1="147.6" x2="63.2" y2="14.1"/> </g> </svg> 
, . , ,

CSS , . . , . . CSS . :

 #Pulse{fill: none; stroke: #D38911; stroke-width: 5; transform: rotateX(80deg);} ._transformer{transform-box: fill-box; transform-origin: center;} 

, _transformer , , . «» <animateTransform> .

- : , Illustrator? …

– , . , . , <path> , .

, ! – , . , – . circle , . animate , 3

 <circle id="Pulse" class="_transformer" cx="100" cy="167" r="0"> <animate id="doPulse" attributeName="r" values="0;85;" dur=".8s" begin="Sign.click" calcMode="spline" keySplines="0,0,.58,1"/> <animate attributeName="stroke-width" values="5;12;" dur=".8s" begin="doPulse.begin"/> <animate attributeName="opacity" values="0.5;1;1;0" keyTimes="0;0.2;0.5;1" dur=".8s" begin="doPulse.begin"/> </circle> 
, CSS


, . : , , . - :


. - , . ,

 <linearGradient id="light-gradient"> <stop offset="0%" stop-color="#ffffff00"/> <stop offset="10%" stop-color="#FFF"/> <stop offset="90%" stop-color="#FFF"/> <stop offset="100%" stop-color="#ffffff00"/> </linearGradient> <mask id="light-mask"> <rect y="0" x="90" class="_transformer" width="20" height="220" fill="url(#light-gradient)" /> </mask> 

, . , , . , <use> , <path> <defs>

 <defs> <path id="question" d="     "/> </defs> ... <use id="front" href="#question"/> <use id="light" href="#question" mask="url(#light-mask)"/> 



, , . . ,

 #light-mask rect{ animation: highlight 4s infinite; } @keyframes highlight { 0% { transform: translate(-100px,0) rotate(-50deg); } 30% { transform: translate(100px,0) rotate(-50deg); } 100% { transform: translate(100px,0) rotate(-50deg); } } 

. . CSS , SMIL.

, . — , . ,

 <g id="Sign" class="_transformer"> <path id="side" d="     "/> <use id="front" href="#question"/> <use id="light" href="#question" mask="url(#light-mask)"/> <animateTransform id="idle" attributeName="transform" type="translate" values="0,0;0,-5;0,0" dur="6s" begin="0s; jump.end" end="click" repeatCount="indefinite" /> <animateTransform id="jump" attributeName="transform" type="translate" calMode="spline" values="0,0;0,10;0,-35;0,5;0,0" keyTimes="0;0.1;0.35;0.6;1" keySpline="0,0,.58,1;0,0,.58,1;.42,0,1,1;0,0,.58,1" dur="1s" begin="idle.end" /> </g> 
,

, , . , additive="sum"

 <animateTransform attributeName="transform" type="scale" additive="sum" values="1,1;1.1,0.8;0.9,1.2;1.1,0.8;1,1" keyTimes="0;0.1;0.35;0.7;1" dur="1s" begin="idle.end" /> 

, , . Ergebnis:

.
? - , , . stroke-dashoffset , . ,

- . ,

 <g id="Particles"> ... </g> <g id="Sign" class="_transformer"> ... </g> 

, ,

 .particles{ opacity:.7; stroke-width:0; ... } 

, . ,

 @keyframes sparks { 0% { stroke-dasharray: 20,200; stroke-width: 5px; } 100% { stroke-dasharray: 4,200; stroke-width: 0px; stroke-dashoffset: -180; } } 

, . , , «». : CSS , , . SMIL, 3 , , 7. , , …

– , - , . CSS, SMIL.

Particles_active ,

 .Particles_active .particles{ animation: sparks .7s; } 

<set> , , ( set )

 <g id="Particles"> <line class="particles" x1="80" y1="162.9" x2="42" y2="59.1"/> ... <line class="particles" x1="80.4" y1="147.6" x2="63.2" y2="14.1"/> <set attributeName="class" to="Particles_active" dur=".7s" begin="jump.begin + .5s"/> </g> 

:

  • ;
  • ;
  • , , , , , ;
  • ;


. , , . 3D , . , , .

Adobe Illustrator, . , . - , . ,

d .


, . Shape Shifter.

, , . , Shape Shifter

, SVG . Shape Shifter , «» SVG. Illustrator. , . , pathData


, , toValue. . «»

. ,

, , Shape Shifter , , , , . , toValue fromValue .

. ,

 <animate attributeName="d" calMode="spline" values="  1;  2;  1" dur="5s" keySpline=".42,0,.58,1;.42,0,.58,1" repeatCount="indefinite" /> 

1 – , 2 –


. Codepen.

, SVG – , . , ,

<set>


Das set- Tag ist eine verkürzte Version von animieren , außer dass es nicht interpolieren kann. Es wird verwendet, um das Attribut für einen bestimmten Zeitraum sofort zu ändern, d. H. arbeitet nach dem Prinzip eines Schalters. Infolgedessen werden die mit der Interpolation verbundenen Attribute ignoriert und kumulative oder relative Animationen werden nicht unterstützt. Der Wert wird nur durch das Attribut an , Attributwerte , aus , indem ignoriert

 <set attributeName="cx" to="200" begin="click" dur="5s" .../> 
Das Element ändert seine Position durch Klicken. Nach 5 Sekunden kehrt es an seine ursprüngliche Position zurück.

Wenn Sie das dur- Attribut nicht angeben, bleibt das Element in diesem Zustand, bis das Dokument erneut geladen wird. Ansonsten ist es ähnlich wie animieren .

<animateTransform>


, . CSS . CSS SMIL , - , , .

?

transform . type 4 – , , , .

translate – . [x, y] , y

 <animateTransform attributeName="transform" type="translate" from="0, -10" to="0, 10" .../> 
Bewegt das Element entlang der Y-Achse.

Drehen - Dreht das Element relativ zum Rotationszentrum. Es werden der Drehwinkel und die Koordinaten des Drehzentrums [Grad, x, y] als Werte verwendet, die Koordinaten des Zentrums sind optional. Standardmäßig befindet sich der Drehpunkt in der oberen linken Ecke des SVG-Dokuments

 <animateTransform attributeName="transform" type="rotate" from="0, 150, 150" to="45, 150, 150" .../> 
Drehen Sie um 45 Grad um einen Punkt mit den Koordinaten 150, 150.

Außerdem kann der Drehpunkt mithilfe der CSS-Eigenschaft für den Transformationsursprung geändert werden. Hierkönnen Sie zusätzlich zu den Koordinaten Prozentsätze angeben. Standardmäßig werden Prozentsätze anhand der Größe des gesamten Dokuments berechnet, sodass Prozentsätze relativ zum Element berechnet werden. Sie müssen die CSS-Eigenschaft für das Transformationsfeld mit dem Füllfeldwert festlegen.

skalieren - skaliert das Objekt. Als Werte werden Gleitkommazahlen im Format [scale] für beide Achsen oder separat für jede Achse [scaleX, scaleY] verwendet (1 entspricht der normalen Größe des Elements). Wenn Sie die Transformationsbox nicht ändernWie oben erwähnt, wird das Element relativ zum gesamten Dokument skaliert. Der leere Raum um das Element ändert sich ebenfalls mit ihm, so dass es visuell so aussieht, als ob das Element zur Seite verschoben ist

 <animateTransform attributeName="transform" type="scale" from="1, 1" to="2, 1" .../> 
Streckt ein Element entlang der X-Achse

skewX oder skewY - verschiebt ein Element relativ zur Achse. Der Wert nimmt den Neigungswinkel [Grad] an . Standardmäßig ist das Verschiebungszentrum die obere linke Ecke, daher funktioniert hier der gleiche Witz mit Transformationsbox und Transformationsursprung wiebei anderen Transformationen

 <animateTransform attributeName="transform" type="skewX" from="0" to="45" .../> <animateTransform attributeName="transform" type="skewY" from="90" to="0" .../> 
Eine Verschiebung entlang X, eine andere entlang Y

Summation und Neudefinition von Transformationen

In animateTransform können Sie weiterhin kumulative und relative Animationen erstellen. Hierverhält sichdas additive Attribut jedochanders. Im Wert von replace überschreibt die Transformation alle vorherigen. Im Summenwert wird dieTransformation mit der vorherigen summiert

 <rect transform="skewY(115)" ...> <animateTransform type="translate" from="-10" to="10" additive="replace" .../> <animateTransform type="rotate" from="0" to="90" additive="sum" .../> </rect> 
In diesem Beispiel wird die Rechteckverschiebung neu definiert, um sich zu bewegen und zu drehen

<animateMotion>


, . animateMotion animate 3 – path , rotate , keyPoints .



from , to , by values , path <mpath> . .

from , to, indem Sie die Koordinaten der Punkte angeben, die gleichen Werte , aber bereits in Form einer Liste

 <animateMotion from="0,0" to="50,100" .../> <animateMotion values="0,0; 0,100; 100,100; 0,0" .../> 

Die Wirkung dieser Methode ist vergleichbar mit der üblichen Verschiebungstransformation. Ein Element bewegt sich geradlinig von einem Punkt zum anderen. Und hier sind die Koordinaten genau wie bei animateTransform relativ . Punkt 0,0 zeigt nicht die obere linke Ecke des Dokuments an, sondern die aktuelle Position des Zielelements. Dieses Merkmal ist bei anderen Methoden zur Bestimmung der Flugbahn vorhanden.

Das Pfadattribut gibt eine Reihe von Befehlen an, wie für das Attribut d . Wenn das Attribut d Befehle als Figuren Umriss das Attribut interpretiert Weg ist es die Linie , entlang der das Element bewegt. Die Koordinaten der Punkte sind ebenfalls relativ, sodass der Pfad bei Punkt 0,0 beginnt

 <animateMotion path="M 0 0 c 3.4 -6.8 27.8 -54.2 56 -37.7 C 73.3 -27.5 89.6 -5.1 81.9 5.9 c -5.8 8.3 -24.7 8.7 -45.4 -0.4" .../> 

Dieser Pfad beschreibt eine solche Kurve


Die letzte Möglichkeit besteht darin, ein <Pfad> -Element eines Drittanbieters als Pfad zu verwenden . Dazu müssen Sie im <mpath> -Tag einen Link zu diesem Element angeben und das Tag selbst muss in <animateMotion> platziert werden . Diese Option hat dieselbe Funktion mit relativen Koordinaten. Im Kern „kopiert“ diese Methode den Wert des Attributs d aus dem Element in das Attribut <path>

 <path id="movement" .../> ... <animateMotion ...> <mpath href="#movement"/> </animateMotion> 
Das Element, das den Pfad definiert, wird möglicherweise nicht einmal im Dokument angezeigt. Sie können es einfach in <defs> definieren.

Drehen Sie ein Element relativ zur Flugbahn.

Mit dem Attribut " Drehen" können Sie das Element in Bewegungsrichtung drehen lassen . Es werden drei Arten von Werten akzeptiert: Auto , Auto-Reverse und eine Zahl, die die Drehung in Grad angibt

 <animateMotion rotate="auto" .../> 

Standardmäßig ist Drehen 0. Jeder numerische Wert erfasst den Winkel in der gesamten Animation. Automatische Modi Auto und Auto-Reverse ändern den Drehwinkel des Elements jeweils tangential zum Pfad. Und sie unterscheiden sich in der Richtung dieser Tangente. In Auto wird es vorwärts gerichtet, während es in Auto-Reverse zurück gerichtet ist .


Wie steuere ich die Bewegung entlang des Pfades?

Die Trajektorie ist eine Kurve, die einen Anfang und ein Ende hat. Diese Punkte werden mit den Zahlen 0 bzw. 1 bezeichnet. Jede Position auf der Kurve kann durch eine Zahl in diesem Bereich bestimmt werden. Durch Auflisten der Punkte im Attribut keyPoints können Sie jede Art von Bewegung entlang des Pfads definieren. Dies reicht jedoch nicht aus, um die Bewegung zu steuern. Dazu benötigen Sie ein ganzes System von Attributen.

Zuerst müssen Sie installieren calcMode Position lineare oder Spline . Im Gegensatz zu anderen Tags ist animateMotion standardmäßig auf Tempo eingestellt (aus irgendeinem Grund möchte die Animation in diesem Modus nicht funktionieren). Sie müssen auch ein Attribut angeben.keyTimes . Nur wenn Sie diese Schritte ausführen, funktioniert die Animation ordnungsgemäß

 <animateMotion keyPoints="0.5; 1; 0; 0.5" keyTimes="0; 0.25; 0.75; 1" calcMode="linear" .../> 
Im Beispiel beginnt die Animation in der Mitte des Pfads, bewegt sich zum Ende, dann zum Anfang und beendet die Bewegung erneut in der Mitte

PS

Beim Umgang mit animateMotion stieß ich auf Informationen, dass das Gleiche wie bei CSS möglich ist. Aber am Ende dieses Artikels hatte ich weder die Kraft noch den Wunsch, damit umzugehen. Für Enthusiasten hinterlasse ich einfach einen Link zur Dokumentation.


Besonderer Dank


Bhudh für die enorme Arbeit an der Korrektur des Artikels

Source: https://habr.com/ru/post/de450924/


All Articles