Einführung in Popmotion Benutzerdefinierter Animationswäscher

Im ersten Teil der Popmotion-Einführungsreihe haben wir die Verwendung gelernt zeitbasiert Animationen wie zwischen und Keyframes. Wir haben auch gelernt, wie man diese Animationen auf dem DOM verwendet, indem man das Performant verwendet Styler.

Im zweiten Teil haben wir gelernt, wie man es benutzt Zeiger Tracking und Aufzeichnung Geschwindigkeit. Wir haben das dann benutzt, um das zu betreiben Geschwindigkeitsbasiert Animationen Frühlingzerfallen, und Physik.

In diesem letzten Teil erstellen wir ein Scrubber-Widget, und wir werden es verwenden, um ein Scrubben durchzuführen Keyframes Animation. Wir machen das Widget selbst aus einer Kombination von Zeiger-Tracking sowie Frühling und zerfallen um es mehr viszeraler zu machen als gewöhnliche Wäscher.

Probieren Sie es selbst aus:

Fertig machen

Markup

Verzweigen Sie zunächst diesen CodePen für die HTML-Vorlage. Da dies ein fortgeschrittenes Tutorial ist, gehe ich nicht alles durch.

Der Hauptvorteil ist, dass der Griff des Wäschers aus zwei besteht div Elemente: .Griff und .Griffbereich.

.Griff ist der runde blaue visuelle Indikator dafür, wo sich der Griff des Wäschers befindet. Wir haben es in ein unsichtbares Element für den Trefferbereich eingepackt, um den Touchscreen-Benutzern das Erfassen des Elements zu erleichtern.

Importfunktionen

Importieren Sie oben in Ihrem JS-Bedienfeld alles, was wir in diesem Tutorial verwenden werden:

const Lockerung, Keyframes, Zeiger, Zerfall, Frühling, Styler, Transformieren, Hören, Wert = popmotion; const Pipe, Klemme, Bedingt, linearSpring, interpolieren = transform;

Elemente auswählen

In diesem Tutorial werden wir drei Elemente benötigen. Wir werden die animieren .Box, ziehen und animieren Sie die .Griffbereich, und messen Sie das .Angebot.

Lass uns auch schaffen Stylers für die Elemente, die wir animieren werden:

const box = document.querySelector ('. box'); const boxStyler = Styler (Box); const handle = document.querySelector ('. handle-hit-area'); const handleStyler = Styler (Griff); const range = document.querySelector ('. range');

Keyframes-Animation

Für unsere scrubbable Animation machen wir die .Box Bewegen Sie sich von links nach rechts mit Keyframes. Wir könnten aber genauso leicht einen schrubben zwischen oder Zeitleiste Animation mit derselben Methode, die später in diesem Tutorial beschrieben wird.

const boxAnimation = Keyframes (Werte: [0, -150, 150, 0], Erleichterungen: [easing.backOut, easing.backOut, easing.easeOut], Dauer: 2000). start (boxStyler.set ('x') ));

Ihre Animation wird jetzt abgespielt. Aber das wollen wir nicht! Lass es für jetzt pausieren:

boxAnimation.pause ();

Ziehen Sie die x-Achse

Es ist Zeit zu benutzen Zeiger um unseren Wäschergriff zu ziehen. Im vorherigen Tutorial haben wir beide verwendet x und y Eigenschaften, aber mit einem Wäscher brauchen wir nur x.

Wir bevorzugen es, unseren Code wiederverwendbar zu halten und einen einzelnen zu verfolgen Zeiger Achse ist durchaus ein häufiger Anwendungsfall. Lassen Sie uns also eine neue Funktion erstellen, die imaginativ aufgerufen wird, pointerX.

Es wird genau so funktionieren Zeiger außer, es wird nur eine einzige Zahl als Argument verwendet und nur eine einzige Zahl ausgegeben (x):

const pointerX = (x) => Zeiger (x). pipe (xy => xy.x); 

Hier können Sie sehen, dass wir eine Methode von verwenden Zeiger namens RohrRohr ist für alle Popmotion-Aktionen verfügbar, die wir bisher gesehen haben, einschließlich Keyframes.

Rohr akzeptiert mehrere Funktionen. Wenn die Aktion ist Startalle Ausgaben werden vor der Ausgabe der Reihe nach durch alle diese Funktionen geleitet aktualisieren Funktion zur Verfügung gestellt Start Feuer.

In diesem Fall ist unsere Funktion einfach:

xy => xy.x

Alles, was es tut, ist die x, y Objekt wird normalerweise von ausgegeben Zeiger und nur das zurückgeben x Achse.

Ereignis-Listener

Wir müssen wissen, ob der Benutzer mit dem Drücken des Griffs begonnen hat, bevor wir mit dem neuen Tracking beginnen pointerX Funktion.

Im letzten Tutorial haben wir das traditionelle verwendet addEventListener Funktion. Dieses Mal verwenden wir eine andere Popmotion-Funktion, die aufgerufen wird Hör mal zuHör mal zu bietet auch eine Rohr Methode sowie Zugriff auf alle Aktionsmethoden, aber wir werden das hier nicht verwenden.

Hör mal zu ermöglicht das Hinzufügen von Ereignis-Listenern zu mehreren Ereignissen mit einer einzigen Funktion, ähnlich wie bei jQuery. So können wir die vorherigen vier Ereignis-Hörer zu zwei verdichten:

listen (handle, 'mousedown touchstart'). start (startDrag); hören (Dokument, 'mouseup touchend'). start (stopDrag);

Bewegen Sie den Griff

Wir brauchen das x des Handles Geschwindigkeit später machen wir es ein Wert, Wie wir im letzten Tutorial gelernt haben, können wir die Geschwindigkeit abfragen. In der Zeile danach definieren wir GriffStyler, hinzufügen:

const handleX = value (0, handleStyler.set ('x'));

Jetzt können wir unsere hinzufügen startDrag und stopDrag Funktionen:

const startDrag = () => pointerX (handleX.get ()) .start (handleX); const stopDrag = () => handleX.stop ();

Im Moment kann der Griff über die Grenzen des Schiebereglers hinaus schrubben, aber darauf kommen wir später zurück.

Schrubben

Jetzt haben wir einen visuell funktionierenden Scrubber, aber die eigentliche Animation wird nicht gelöscht.

Jeden Wert hat ein abonnieren Methode. Dies ermöglicht es uns, mehrere Abonnenten anzuschließen, wenn die Wert Änderungen. Wir wollen das suchen Keyframes Animation wann immer handleX Aktualisierung.

Messen Sie zuerst den Schieberegler. In der Zeile danach definieren wir Angebot, hinzufügen:

const rangeWidth = range.getBoundingClientRect (). width;

keyframes.seek akzeptiert einen Fortschrittswert, wie von ausgedrückt 0 zu 1, während unser handleX wird mit Pixelwerten von gesetzt 0 zu rangeWidth.

Wir können von der Pixelmessung in eine konvertieren 0 zu 1 Bereich durch Teilen der aktuellen Pixelmessung durch rangeWidth. In der Zeile nach boxAnimation.pause (), Füge diese abonnierte Methode hinzu:

handleX.subscribe (v => boxAnimation.seek (v / rangeWidth));

Wenn Sie jetzt mit dem Scrubber spielen, wird die Animation erfolgreich scrubben!

Die Extrameile

Frühlingsgrenzen

Der Wäscher kann immer noch außerhalb der Grenzen des gesamten Bereichs gezogen werden. Um das zu lösen, haben wir könnte benutze einfach eine Klemme Funktion, um sicherzustellen, dass wir keine Werte außerhalb von ausgeben 0, rangeWidth.

Stattdessen gehen wir noch einen Schritt weiter und befestigen Federn am Ende unseres Schiebereglers. Wenn ein Benutzer den Griff über den zulässigen Bereich hinaus zieht, wird er zurückgezogen. Wenn der Benutzer den Griff freigibt, wenn er sich außerhalb des Bereichs befindet, können wir ein verwenden Frühling Animation zum Zurückschnappen.

Wir machen diesen Prozess zu einer einzigen Funktion, die wir dem zur Verfügung stellen können pointerX Rohr Methode. Durch die Erstellung einer einzigen, wiederverwendbaren Funktion können wir diesen Code mit jeder Popmotion-Animation mit konfigurierbaren Bereichen und Federstärken wiederverwenden.

Lassen Sie uns zuerst eine Feder auf die äußerste linke Grenze anwenden. Wir verwenden zwei Transformatoren, bedingt und linearSpring.

const springRange = (min, max, Stärke) => bedingt (v => v < min, linearSpring(strength, min) );

bedingt übernimmt zwei Funktionen, eine Zusicherung und einen Transformator. Die Zusicherung erhält den angegebenen Wert und kehrt entweder zurück wahr oder falsch. Wenn es zurückkehrt wahr, der zweiten Funktion wird der Wert bereitgestellt, der transformiert und zurückgegeben werden soll.

In diesem Fall lautet die Aussage: "Wenn der angegebene Wert kleiner ist als Mindest, geben Sie diesen Wert durch linearSpring Transformator. "Die linearSpring ist eine einfache Federfunktion, die im Gegensatz zum Physik oder Frühling Animationen, hat keine Vorstellung von Zeit. Gib es a Stärke und ein Ziel, und es wird eine Funktion erstellt, die einen beliebigen Wert mit der definierten Stärke in Richtung des Ziels "anzieht".

Ersetzen Sie unsere startDrag Funktion mit diesem:

const startDrag = () => pointerX (handleX.get ()) .pipe (springRange (0, rangeWidth, 0.1)) .start (handleX);

Wir übergeben jetzt den Zeiger x versetzt durch unsere springRange Wenn Sie also den Griff an der am weitesten links liegenden Seite ziehen, werden Sie feststellen, dass er zurückgezogen wird.

Wenn Sie dasselbe auf die ganz rechte Seite anwenden, müssen Sie eine Sekunde erstellen bedingt mit der ersten Verwendung des Stand-Alone Rohr Funktion:

const springRange = (min, max, Stärke) => Rohr (bedingt (v => v < min, linearSpring(strength, min) ), conditional( v => v> max, linearSpring (Stärke, max)));

Ein weiterer Vorteil des Komponierens einer Funktion wie springRange ist, dass es sehr überprüfbar wird. Die zurückgegebene Funktion ist wie alle Transformatoren eine reine Funktion, die einen einzelnen Wert annimmt. Sie können diese Funktion testen, um zu sehen, ob sie Werte durchlässt, die innerhalb liegen Mindest und max unverändert, und wenn es gilt, werden die Werte, die außerhalb liegen, mit Federn versehen.

Wenn Sie den Griff loslassen, während er außerhalb des Bereichs liegt, sollte er jetzt wieder in den Bereich zurückspringen. Dafür müssen wir die anpassen stopDrag Funktion zu feuern a Frühling Animation:

const stopDrag = () => const x = handleX.get (); (x < 0 || x > rangeWidth)? snapHandleToEnd (x): handleX.stop (); ;

Unsere snapHandleToEnd Funktion sieht so aus:

const snapHandleToEnd = (x) => spring (von: x, Geschwindigkeit: handleX.getVelocity () bis: x < 0 ? 0 : rangeWidth, damping: 30, stiffness: 5000 ).start(handleX);

Sie können sehen, dass zu ist entweder als gesetzt 0 oder rangeWidth Je nachdem auf welcher Seite des Schiebereglers der Griff gerade sitzt. Indem du mit spielst Dämpfung und Steifheit, Sie können mit verschiedenen Federfühlen spielen.

Momentum Scrollen

Ein schöner Aspekt von iOS-Scrubber, den ich immer zu schätzen wusste, war, dass der Griff nach und nach verlangsamt würde und nicht zum Stillstand gekommen wäre. Wir können das einfach mit dem replizieren zerfallen Animation.

Im stopDrag, ersetzen handleX.stop () mit MomentumScroll (x).

Dann auf der Zeile nach dem snapHandleToEnd Funktion, fügen Sie eine neue Funktion hinzu MomentumScroll:

const momentumScroll = (x) => decay (from: x, Geschwindigkeit: handleX.getVelocity ()). start (handleX);

Wenn Sie jetzt den Griff werfen, wird er allmählich gestoppt. Es wird auch außerhalb des Bereichs des Schiebereglers animiert. Wir können damit aufhören, indem wir das übergeben Klemme Transformator zum decay.pipe Methode:

const momentumScroll = (x) => decay (von: x, Geschwindigkeit: handleX.getVelocity ()). pipe (clamp (0, rangeWidth)) .start (handleX);

Fazit

Durch die Kombination verschiedener Popmotion-Funktionen können wir einen Wäscher erstellen, der ein bisschen mehr Leben und Verspieltheit bietet als üblich.

Durch die Nutzung Rohr, Wir setzen einfache reine Funktionen zu komplexeren Verhaltensweisen zusammen und lassen die Verbundwerkstoffe überprüfbar und wiederverwendbar.

Nächste Schritte

Wie wäre es mit diesen Herausforderungen?

  • Machen Sie das Ende der Momentum-Bewegung mit einem Sprung, wenn der Griff auf ein Ende des Scrubbers trifft.
  • Machen Sie den Griff an einen beliebigen Punkt im Wäscher animiert, wenn ein Benutzer auf einen anderen Teil der Bereichsleiste klickt.
  • Fügen Sie vollständige Wiedergabesteuerelemente hinzu, beispielsweise eine Wiedergabe- / Pause-Taste. Aktualisieren Sie die Position des Scrubber-Griffs im Verlauf der Animation.