UX Abo

Neuer Workshop: "UX Metrics - Erfolgsmessung im UX Design".

Zeigt her!
Close

Animationen - die neuen Features von Angular 4.2

Animationen gehören zum Frontend wie die Butter aufs Brot. Sie machen ein wunderschönes Design zu einem lebendigen, reagierenden Gegenüber und sind damit aus einer erfolgreichen User Experience nicht wegzudenken.

Früher wurden Animationen, die über den Hover-State hinausgingen, mit Flash umgesetzt, gleichzeitig wurde aber auch Javascript (und dessen Libraries, zb jQuery) immer beliebter. 2011 begannen die Browser, CSS-Animationen zu unterstützen. Eine Vielzahl an Eigenschaften wurde so animierbar; ganz einfach von einem Wert zum anderen, oder gar als Keyframe-Animation, die bis in die Unendlichkeit loopen kann. Und Javascript spielte hier stets eine nicht unwesentliche Rolle: es kann in den DOM eingreifen, Klassen vergeben, Eigenschaften verändern. Libraries und Frameworks bieten dazu noch recht mächtige und einfach zu bedienende Konzepte.

Angular

Als AngularJS (Version 1) kam, waren die Animationen noch recht übersichtlich.

Auf Änderungen, die AngularJS im DOM veranlasste, konnte im CSS reagiert werden. Wurde zb. ein Element hinzugefügt, so konnte man dieses Element gezielt animieren. Dazu wurden von AngularJS ein paar Klassen vergeben, wenn ein Element mit ng-show angezeigt wurde: .ng-hide gleich zu Beginn, .ng-hide-remove für die Dauer der Animation, und .ng-hide-remove-active wenn die Animation abgeschlossen war. Das war zwar manchmal semantisch nicht ganz nachvollziehbar (warum ng-hide-remove, wenn es doch auch beispielsweise ng-show sein hätte können), aber im Großen und Ganzen schon recht praktikabel.

 
Nun ist AngularJS nicht mehr aktuell. 2016 kam Angular 2 – und bei diesem Release blieb kein Stein auf dem anderen. Natürlich auch bei den Animationen nicht. Man kann noch dynamisch Klassen vergeben und Elemente dadurch zum Leben erwecken, die neuen Komponenten haben allerdings eine eigene Animations-DSL (Domain Specific Language) erhalten, die sich fundamental zu den bisherigen Konzepten unterscheidet.

Jedes Element einer Komponente kann mit einem Animationstrigger ausgestattet bzw. diesem zugeordnet werden. Diese Trigger beinhalten states (mit Styling-Anweisungen), und sobald der state geändert wird (zb. ‘inactive’ zu ‘active’) , kommt es zur entsprechenden Animation (leicht verkürzt dargestellt). Hier gibt es jedoch einige Einschränkungen in dieser Art der Animation, die in vielen Fällen den Rückweg zu klassischen Klassen-getriggerten Animationen gefordert haben. Auch der Release von Angular 4 hat hier noch nicht die erhofften Änderungen gebracht.

ng-conf 2017

Auf der diesjährigen ng-conf hat Matias Niemela (Angular Developer für den Bereich Animation) einige Features vorgestellt, die die Funktionalität der Animationsmöglichkeiten enorm stärken. Wir haben uns den Release-Candidate der Version 4.2 mal näher angesehen und die einige Aspekte durchprobiert. (Achtung – Die im Video gezeigten Konzepte sind im RC 4.2 teilweise etwas anders umgesetzt)

 

Wiederverwendbare Animationen mit dynamischen Werten

Bisher konnte man, wenn man Animationen wiederverwenden wollte, die Animationen in extra Files auslagern und bei Bedarf wieder importieren. Die neuen, wiederverwendbaren Animationen funktionieren ähnlich, man erstellt die Animation, und kann diese dann in den jeweiligen Triggern ausführen:

Die Fade-In-Animation wird angelegt:

//animations.ts
export let fadeIn = animation([
  style({opacity:0}),
  animate(1000', style({opacity:1}))
]);

Mit der Funktion useAnimation kann die importierte Animation ausgeführt werden:

//app.animations.component.ts
import {fadeIn} from './animations';
export const myAnimations = trigger('fade', [
  transition('* => in', [
    useAnimation(fadeIn)
  ])
]);

Diese Art der Animations-Wiederverwendung ist schon ganz praktisch, ihre wahre Stärke spielt sie aber aus, wenn es um dynamische Werte geht: Man kann dieser Animation nämlich Parameter mitgeben, sowohl Werte, die den Element-Eigenschaften zugeordnet werden, als auch die Dauer der Animation.

Die Fade-In-Animation wird mit Variablen versehen, am Ende können Standardwerte vergeben werden.

//animations.ts
export let fadeIn = animation([
  style({opacity:'{{ start }}'}),
  animate('{{time}}', style({opacity:'{{ end }}'}))
], { params: { time: '1000ms', start: 0, end: 1 }});

Die Parameter werden als Objekt der useAnimation-Funktion übergeben.

//app.animations.component.ts
import {fadeIn} from './animations';
export const myAnimations = trigger('fade', [
  transition('* => in', [
    useAnimation(fadeIn,{ params: { time: '500ms', start: 0.3, end: 0.9 }})
  ])
]);

Sub-Elemente animieren
Bisher war es nicht möglich, über die Angular Animations-DSL Kindelemente eigens zu animieren. Das, und die fehlende Möglichkeit, Werte dynamisch zu übergeben, haben uns in den meisten Fällen zu den Klassen-basierten Animationen getrieben, da uns oftmals der Mehrwert fehlte. Das ändert sich jetzt. Das langersehnte query hat es in den Release-Candidate geschafft! Und gemeinsam mit group ist das schon ziemlich fein für Animationen, die mehrere Elemente betreffen. Das Beispiel zeigt eine Animation die folgendermaßen abläuft: Der Basis-Container wird auf height:0 und overflow:hidden gesetzt, damit nichts von ihm oder seinen Kindern zu sehen ist. Der inner-container wird 50px nach links versetzt, der .text-container um 20px nach unten. Danach geht’s schon ans Animieren: die Höhe des Basis-Containers wird automatisch errechnet, der inner-container wird sichtbar und kommt von links zur Zielposition – mit einem Delay von 300ms. Danach wird der text-container von unten ein-animiert.

 
Mithilfe des query-Selectors können auf Kindelemente (zb .inner-container, .text) zugegriffen werden, und mit group werden dann verschiedene Animationen gleichzeitig ausgeführt:

transition(':enter', [
  style({overflow:'hidden', height:'0'}),
  query('.inner-container', style({opacity:0, transform:'translateX(-50px)'})),
  query('.text', style({transform:'translateY(20px)'})),
  group([
    animate('600ms ease-out', style({height:'*'})),
    query('.inner-container', animate('500ms 300ms ease-out', style({opacity:1, transform:'translateX(0px)'}))),
  ]),
  query('.text', animate('300ms ease-out', style({transform:'translateY(0px)'}))),
])

Ausblick

Es gibt noch einige weitere Neuerungen, wie beispielsweise neue Funktionen für Routen-Animationen, oder programmatische Animationen. Letztere dürften ihre Stärke wohl dann ausspielen, wenn die Animationsdauer und -werte von externen Quellen abhängen, wie dies beispielsweise bei einem Fortschrittsbalken eines Uploads der Fall sein könnte.

Aber jetzt warten wir mal auf den offiziellen Release (und eine offizielle Dokumentation), da zwischen der angesprochenen Keynote und 4.2-rc.1 schon diverse Unterschiede festzustellen sind. Wir sind jedenfalls euphorisch und freuen uns auf die neuen Features!

Du willst mit jemanden über das Thema plaudern?

Einen kostenlosen Termin mit CEO Susanne vereinbaren!

Lukas Kindermann

Meine Rolle bei Liechtenecker: Omnom-Fanboy Wenn es weder IT noch Digitalisierung gäbe, wäre mein Beruf: Handwerker Mein Herz schlägt für: Sachen machen und Erdäpfel essen

Interesse mit uns zu arbeiten?

Lass uns plaudern …

oder vereinbare gleich mit unserer CEO Susanne einen kostenlosen Termin.