Animationstricks mit Exponential Smoothing
- Seit ich angefangen habe, an animationsbezogenen Dingen zu arbeiten, gibt es eine einfache Animationstechnik, die ich fast immer verwendet habe.
- Diese Technik wird an vielen Stellen eingesetzt, etwa bei Kamerarotation und -bewegung, der Figurenbewegung in rundenbasierten Spielen, der Bewegung von UI-Elementen oder der Glättung von Lautstärkeänderungen in Audio-Bibliotheken.
- Die Technik ist nicht neu; vielleicht hast du schon davon gehört oder sie selbst verwendet. Ich werde aber einige Beispiele und die mathematischen Grundlagen erklären.
Toggle-Button
- Nehmen wir an, wir bauen eine UI-Komponente, zum Beispiel einen Toggle-Button.
- Die Position des Schalters im Toggle-Button wird abhängig vom Zustand berechnet und auf
max_x gesetzt, wenn er eingeschaltet ist, und auf min_x, wenn er ausgeschaltet ist.
- Das funktioniert gut, wirkt ohne Animation aber etwas leblos.
- Animation sorgt nicht nur für visuelle Eleganz, sondern hilft Nutzern auch zu verstehen, was gerade passiert.
- Statt den Toggle-Indikator sofort an die neue Position zu setzen, ändern wir ihn so, dass er sich sanft bewegt.
- Jetzt muss die Animation aktualisiert werden, was den Nachteil hat, dass die Bewegung wie mit konstanter Geschwindigkeit aussieht.
- Man kann hier eine Easing-Funktion hinzufügen und zum Beispiel
3t^2-2t^3 oder sqrt(t) verwenden.
- Die Unterschiede zwischen solchen Easing-Funktionen sieht man besser, wenn man die Animation verlangsamt.
- Jetzt muss man statt nur die Schalterposition zu aktualisieren auch den Animationszustand nachverfolgen.
- Wenn man
sqrt verwendet, muss man abhängig von der Animationsrichtung explizit unterschiedliche Easing-Funktionen einsetzen.
- Was am besten aussieht, ist Geschmackssache, aber
sqrt sieht am besten aus. Der Schalter startet damit sehr schnell und wird beim Annähern an das Ziel schön langsamer.
- Der Nachteil dieser Version ist, dass selbst der einfachste Fall ziemlich viel Verwaltungsaufwand erfordert und dass es eine sprunghafte Diskontinuität gibt, wenn der Nutzer mitten in der Animation klickt.
Kamerabewegung
- Nehmen wir an, eine Karte und eine Kamera scrollen oder bewegen sich durch die Umgebung.
- Auch hier ist es gut, Animation hinzuzufügen.
- Es wird Code gezeigt, der mit konstanter Geschwindigkeit interpoliert.
- Das Zittern nach Abschluss der Animation entsteht, weil
target.x - position.x abwechselnd positiv und negativ wird.
- Statt
sign(delta) braucht man eine Funktion, die das Delta clampt.
- Diese Methode ist für etwas Einfaches ziemlich kompliziert.
- Es sieht seltsam aus, wenn die Animationsgeschwindigkeit höher ist als das Erreichen des Animationsendes.
- Man könnte die Eingaben des Nutzers ignorieren, solange die Animation aktiv ist, aber das wäre eine sehr frustrierende Nutzererfahrung.
- Die perfekte Lösung ist natürlich Exponential Smoothing.
- Im Vergleich zum Toggle-Button-Beispiel ändert sich der Code kaum.
Wie es intern funktioniert
- Es wird erklärt, was
1 - exp(- speed * dt) ist und wie es funktioniert.
- Zunächst wird mit einer einfachen Version begonnen, bei der die Bewegungsgeschwindigkeit proportional zur Distanz zwischen der aktuellen
position und der neuen Zielposition target gemacht wird.
- Diese Methode braucht keinen weiteren Zustand außer aktueller Position und Zielposition und passt sich automatisch an, selbst wenn sich
target plötzlich ändert.
- Es gibt jedoch ein kleines Problem: Wenn
speed * dt größer als 1 ist, schießt die Position über das Ziel hinaus.
- Um dieses Problem zu lösen, kann man den Wert auf 1 clampen.
- Der Grund, warum
speed * dt zu groß wird, ist entweder ein zu großer speed-Wert oder ein zu großes dt.
- Für Animationen wäre es schön, wenn beim Anwenden von
dt alles perfekt funktionieren würde.
Differentialgleichungen (oh nein)
- Es wird ein zweistufiger Ansatz vorgestellt, um das Problem zu lösen.
- Dass
position += (target - position) * speed * dt für kleine dt funktioniert, aber für große dt versagt, ist ein typisches Problem numerischer Lösungen von Differentialgleichungen.
- Es wird untersucht, was diese Gleichung eigentlich löst.
- Es wird erklärt, dass
position += (target - position) * (1 - exp(- speed * dt)) die korrekte Formel für alle dt ist.
Wahl der Geschwindigkeit
- Normalerweise denkt man bei Animationen in Dauerangaben.
- Mit der Exponentialformel wird eine Animation technisch gesehen erst nach unendlicher Zeit vollständig abgeschlossen.
- Die Bedeutung des Parameters
speed ist, dass 1 / speed die Zeit ist, in der position dem target um den Faktor e = 2.71828... näher kommt.
Exponential Smoothing
- Wenn man nach „Exponential Smoothing“ sucht, findet man möglicherweise einen Wiki-Artikel, der völlig unrelated wirkt, tatsächlich aber eine Formel enthält, die der in diesem Beitrag sehr ähnlich ist.
- Wenn man annimmt, dass
dt immer gleich bleibt und sich target bei jeder Iteration ändert, kann man die Werte über die Iterationsnummer indizieren und etwas wie position[i] = (target[i] - position[i - 1]) * factor berechnen.
Titel des letzten Absatzes
- Ich hatte die Idee zu diesem Beitrag schon seit einigen Monaten und freue mich, ihn endlich fertiggestellt zu haben.
- Danke fürs Zuschauen des Devlogs und fürs Lesen.
Meinung von GN⁺
- Dieser Artikel erklärt die Technik des Exponential Smoothing, die verwendet wird, um Animationen weich und natürlich wirken zu lassen. Sie trägt dazu bei, die User Experience zu verbessern und die Intuitivität von Interfaces zu erhöhen.
- Exponential Smoothing kann auch nützlich sein, um physische Bewegungen zu simulieren, etwa in der Spieleentwicklung, um Figurenbewegungen oder Kamerafahrten natürlicher wirken zu lassen.
- Die Technik ist besonders wirksam, wenn Elemente einer Benutzeroberfläche Zustandsänderungen durchlaufen und diese visuell dargestellt werden sollen. Zum Beispiel kann die Bewegung von Slidern oder Schaltern deutlich sanfter erscheinen.
- Kritisch betrachtet kann Exponential Smoothing es schwieriger machen, Geschwindigkeit und Dauer von Animationen exakt zu steuern. Das kann einschränkend sein, wenn Designer einen bestimmten Animationseffekt sehr präzise abstimmen wollen.
- Andere Animationsbibliotheken oder Frameworks mit ähnlicher Funktionalität sind etwa GreenSock Animation Platform (GSAP) oder anime.js; sie bieten zusammen mit verschiedenen Easing-Funktionen eine feinere Kontrolle über Animationen.
- Bei der Einführung von Exponential Smoothing sollte man ein Gleichgewicht zwischen natürlicher Wirkung und präziser Steuerbarkeit finden. Der Vorteil ist eine bessere User Experience, der Nachteil kann die schwierigere Feinabstimmung des Timings sein.
1 Kommentare
Hacker-News-Kommentare
Zusammenfassung des ersten Kommentars:
smoothstep()-Funktion ist, sondern ein zustandsloser Ansatz, der unterschiedliche Eingaben konsistent verarbeitet.Zusammenfassung des zweiten Kommentars:
Zusammenfassung des dritten Kommentars:
sqrt) besser sei als kubisch.Zusammenfassung des vierten Kommentars:
Zusammenfassung des fünften Kommentars:
Zusammenfassung des sechsten Kommentars:
Zusammenfassung des siebten Kommentars:
Zusammenfassung des achten Kommentars:
Zusammenfassung des neunten Kommentars:
Zusammenfassung des zehnten Kommentars: