Mathe vor Ostern: Easing
Rolf B
- animation
- javascript
- programmiertechnik
Hallo,
easing-Funktionen sind ja etwas, das die diversen Animationstools von Haus aus mitbringen.
Es ist aber nicht so einfach, wenn man bspw. mit SVG einen Pfeil animieren möchte, der von Länge 0 entlang eines Pfades wächst und dessen Pfeilspitze beim Wachsen mitläuft (und natürlich dabei in die richtige Richtung zeigt).
Das Problem "Pfeilspitze" ist gut machbar, akt. Punkt und letzten Punkt nehmen, Differenz, Math.atan2 und man hat die Richtung. Das mit SVG um den richtigen Punkt zu drehen ist nochmal ein bisschen Drama, aber geht auch.
Aber nun. Ich habe einen Path für den Pfeil.
"M410,580 A100,40,0 0 1 310,620 A290,420,0 0 1 020,200"
So ein Schnörkel untenrum und dann nach links oben weg.
So was hier... - mit Space die Animation starten.
Mit getTotalLength()
komm ich an die Länge L dieses Pfades ran. Und mit getPointAtLength(l)
bekomm ich die Koordinaten des Punktes an der Stelle l
auf dem Pfad. Wollte ich also meinen Pfeil mit linearem Tempo wachsen lassen, würde ich einfach in requestAnimationFrame Dreisatz machen und zum Zeitpunkt t der Animationsdauer d rechnen: $$\displaystyle l = \frac{t}{d}\cdot L$$
Naja, ganz einfach auch nicht, ich muss ja schauen, in welchem Pfadsegment ich mit meinem Punkt bin und nur diesen Teil des Pfades ins d-Attribut des <path> Elements schieben. Und das für jeden Animationsschritt, denn der Endpunkt ändert sich ständig.
SMIL Animation hilft mir übrigens nicht. Die hab ich zuerst benutzt, aber der Endpunkt des Pfades bewegt sich entlang einer Geraden, nicht entlang des Pfades selbst. Nein, das möchte ich nicht.
Aber ich möchte nicht linear. Ich möchte ein ease-in-out Verhalten. Ich könnte die h10-Funktion der Kubisch-Hermiteschen Splines verwenden, die macht ein bisschen ease-in-out. Aber ich will den Effekt stärker, und ich hätt's auch gern konfigurierbar.
Meine aktuelle Lösung ist ein Spline von (0,0) nach (d,L), mit Richtungsvektoren (2d,0) vorn und hinten für einen symmetrischen ease-in-out. Dieser Spline modelliert die gewünschte Timing-Kurve, nicht etwa den Pfeilverlauf.
Problem dabei: Parameter der Spline-Funktion ist t - und zwar nicht mein t, sondern ein Wert im Intervall $$[0, 1]$$, mit dem man alle x- und y-Koordinaten auf der Splinekurve bekommt.
Ich muss also die kubische Funktion $$S_x(t)$$, die mir die X-Koordinate der Splinekurve liefert, umkehren, um t zu erhalten, und bekomme dann über $$S_y(t)$$ das y. Setzt natürlich voraus, dass der Spline eine Funktion und keine Relation ist - wenn die Richtungsvektoren zu lang werden, läuft so ein Ding ja auch mal rückwärts oder dreht ein Löckchen. Aber das ist dann GIGO[1].
Ich mache also eine Nullstellensuche für die Funktion $$S_x$$ mit Intervallhalbierung über $$t \in [0,1]$$, um das passende t zum x zu finden. Und kriege ein y. Sieht auch am Ende gar nicht so schlecht aus.
Aber - BOAH EY - ist das ein umständliches Vorgehen…
Ich würde lieber mit Spatzen auf Kanonen schießen als umgekehrt. Gibt's dafür eine elegantere Lösung? Kann SVG/SMIL sowas vielleicht sogar von Hause aus und ich breche mir die Finger ab für nichts?
Rolf
Garbage In, Garbage Out ↩︎
Servus!
Ich würde lieber mit Spatzen auf Kanonen schießen als umgekehrt. Gibt's dafür eine elegantere Lösung? Kann SVG/SMIL sowas vielleicht sogar von Hause aus und ich breche mir die Finger ab für nichts?
SMIL - die keySplines- und keyTimes-Attribute kennst Du, oder?
Beispiel: SMIL#keySplines
Herzliche Grüße
Matthias Scharwies
Hallo Matthias,
hatte ich mir angeschaut, aber ich weiß nicht ob die mir helfen.
Wie gesagt, wenn ich animate verwende, kann ich zwar einen Path von "M0,0" nach "M0,0 A... A... A..." animieren, mit p1, p2, p3 als jeweiligen Endpunkten der A Segmente, aber dann wandert der Endpunkt der Animationsschritte auf einem Geradenzug von 0,0 über p1 und p2 nach p3 und das bewirkt, dass der path nicht stetig wächst sondern rumeiert.
Ich hatte als Baustelle etwas in dieser Art in der Seite. Habe ich jetzt aktiviert und neu hochgeladen. http://www.borchmann.one/test/animationspline.html
Lass es ablaufen und drück dann mal Space.
Das Timing der animate-Sequenz ist gruselig, aber das kriegt man mit keySplines und keyTimes mutmaßlich wie gewünscht hin. Aber der Bewegungsablauf wird damit wohl unverändert bleiben, oder? Den Pfeil müsste man wohl mit animateMotion und rotate=auto lösen können - aber solange der Pfad sich beim Animieren durch die Gegend windet, hilft das auch nicht viel.
Wofür ich das haben will, kannst Du Dir sicher denken 😉
Rolf
Servus!
Hallo Matthias,
hatte ich mir angeschaut, aber ich weiß nicht ob die mir helfen.
Wie gesagt, wenn ich animate verwende, kann ich zwar einen Path von "M0,0" nach "M0,0 A... A... A..." animieren, mit p1, p2, p3 als jeweiligen Endpunkten der A Segmente, aber dann wandert der Endpunkt der Animationsschritte auf einem Geradenzug von 0,0 über p1 und p2 nach p3 und das bewirkt, dass der path nicht stetig wächst sondern rumeiert.
Ich hatte als Baustelle etwas in dieser Art in der Seite. Habe ich jetzt aktiviert und neu hochgeladen. http://www.borchmann.one/test/animationspline.html
Lass es ablaufen und drück dann mal Space.
Das Timing der animate-Sequenz ist gruselig, aber das kriegt man mit keySplines und keyTimes mutmaßlich wie gewünscht hin. Aber der Bewegungsablauf wird damit wohl unverändert bleiben, oder? Den Pfeil müsste man wohl mit animateMotion und rotate=auto lösen können - aber solange der Pfad sich beim Animieren durch die Gegend windet, hilft das auch nicht viel.
So animierst du ja den Pfad (bzw. die d-Koordinaten) selbst.
Wenn Du den Pfeil entlang eines Pfades laufen lassen willst, musst Du SMIL/animateMotion oder CSS-offset verwenden.
Ob der Animationspfad sichtbar ist, entscheidest du. Die blaue Färbung des Pfades (dessen d-Koordinaten ja nicht geändert werden) kannst du mit stroke-dashoffset verändern.
Wofür ich das haben will, kannst Du Dir sicher denken 😉
Ja!
Herzliche Grüße
Matthias Scharwies
Hallo Matthias,
So animierst du ja den Pfad (bzw. die d-Koordinaten) selbst.
Sicher, will ich ja. Der Pfeil soll wandern und den Pfad hinter sich herziehen. So, wie's beim Druck auf SPACE aussieht.
Rolf