Rolf B: Mathe vor Ostern: Easing

Beitrag lesen

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


  1. Garbage In, Garbage Out ↩︎