Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
An example when you need dynamic properties inside of an angular animation and need to implement the animation in ts code and not in the animation DSL
<card (click)="clicked()">
<card-content>
<card-title [ngStyle]="{'font-size': fontsize}">{{itemDetails.name}}</ion-card-title>
<icon [svgIcon]="itemDetails.icon" [style.height.px]="iconWidthHeight"
[style.width.px]="iconWidthHeight" ></icon>
</card-content>
</card>
import {animate, AnimationBuilder, AnimationPlayer, style, OnChanges} from "@angular/animations";
import {Component, ElementRef, HostBinding, Input} from "@angular/core";
@Component({
templateUrl: 'animated-item.component.html',
selector: 'animated-item',
})
export class AnimatedItemComponent implements OnChanges {
itemPlayer: AnimationPlayer;
iconPlayer: AnimationPlayer;
titlePlayer: AnimationPlayer;
leftPosition: number;
topPosition: number;
fontsize: string;
iconWidthHeight = 0;
@Input()
itemDetails: MyCustomDetailClass;
@HostBinding("style.width.px")
width: number;
@HostBinding("style.height.px")
height: number;
constructor(private el: ElementRef, private animationBuiler: AnimationBuilder) {}
animate() {
//... calculate Heights,widths and all other parameters, details omitted bc clarity
this.destroyPlayers();
const itemAnimation = this.createItemAnimation(width, height, leftPosition, topPosition);
const iconAnimation = this.createIconAnimation(iconWidthHeight);
const titleAnimation = this.createTitleAnimation(fontsize);
this.itemPlayer = itemAnimation.create(this.el.nativeElement);
this.iconPlayer = iconAnimation.create(this.icon.nativeElement);
this.titlePlayer = titleAnimation.create(this.title.getNativeElement());
this.itemPlayer.play();
this.iconPlayer.play();
this.titlePlayer.play();
this.itemPlayer.onDone(() => {
//a CustomEvent not only bubbles to the immediate (angular) parent element but can bubble up to the root element
//this event happens when the animation is done
const ev = new CustomEvent("animationDone", {bubbles: true});
this.el.nativeElement.dispatchEvent(ev);
})
}
clicked() {
//a CustomEvent not only bubbles to the immediate (angular) parent element but can bubble up to the root element
//this event happens when the component/item is clicked and triggers the animatin (implementation detail)
const ev = new Event("wasClicked", {bubbles: true, cancelable: true});
this.el.nativeElement.dispatchEvent(ev);
}
ngOnChanges() {
this.animate();
}
private createTitleAnimation(fontsize: string) {
return this.animationBuiler.build([
style({
"font-size": this.fontsize,
}),
animate(`500ms ${this.delay}ms cubic-bezier(.35, 0, .25, 1)`, style({
"font-size": fontsize
}))
]);
}
private createIconAnimation(iconWidthHeight: number) {
return this.animationBuiler.build([
style({
width: this.iconWidthHeight,
height: this.iconWidthHeight,
}),
animate(`500ms ${this.delay}ms cubic-bezier(.35, 0, .25, 1)`, style({
width: iconWidthHeight + "px",
height: iconWidthHeight + "px",
}))
]);
}
private createItemAnimation(width: number, height: number, leftPosition: number, topPosition: number) {
return this.animationBuiler.build([
style({
width: this.width,
height: this.height,
transform: `translate3d(${this.leftPosition}px, ${this.topPosition}px, 0)`
}),
animate(`500ms ${this.delay}ms cubic-bezier(.35, 0, .25, 1)`, style({
width: width + "px",
height: height + "px",
transform: `translate3d(${leftPosition}px, ${topPosition}px, 0)`
}))
]);
}
//when there is already an animation running you have to stop/destroy it first, before you create a new one
private destroyPlayers() {
if (this.itemPlayer) {
this.itemPlayer.destroy();
}
if (this.iconPlayer) {
this.iconPlayer.destroy();
}
if (this.titlePlayer) {
this.titlePlayer.destroy();
}
}
}
<animated-item *ngFor="let item of items; let i = index" [itemDetails]="item"
(wasClicked)="selectItemSoAnimationWillBeTriggered(item)">
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment