I would like to animate multiple elements from a starting position to an end position in an individual sequence (when card0
finishes, card1
should start). The starting position element is defined in a different Angular component. The cards are defined in an Observable
element and are currently displayed at the same time when you click the button.
In the image you can see that card0
should move from start
to the bottom card0
element. After that, the same should happen with card1
, then with card2
I currently only managed to animate the observable elements. I would like to find out how to animate them individually and how to let them flow from a starting position from the other component.
Here is a StackBlitz
CodePudding user response:
it's a bit complex because to move a tag from a position to another you need know the position initial and final.
Imagine you has an animation like:
animations:[
trigger('move',[
transition('false => true',[
style({ 'top': 0,'left':0 }),
animate('200ms', style({top:'*',left:'*'})),
])])
]
This animation "move" the element from the position absolute 0,0 to the position absolute that the element has really. But we don't want the element with style={position:absolute}
. So we need calculate. To calculate, we are going to get the elements in a ViewChildren and use a variable to position
@ViewChildren('card') cards:QueryList<ElementRef>
pos:any[]=[]
And when animation start, we are going to calculate the position of the elements.
startAnimation(){
this.pos=this.cards.map(x=>{
const rect=x.nativeElement.getBoundingClientRect();
return {
top:(window.scrollY rect.top) 'px',
left:(window.scrollX rect.left) 'px',
position:'absolute'
}
})
this.count=0;
}
Then we are going to use a variable "count", and when a animation is done increment the variable
animationDone(incr:number)
{
this.count =incr
if (this.count>3) //<--if the variable is the last animation
this.pos=this.pos.map(x=>null) //<--we equal to null the array "pos"
}
Use visibility hidden and visibility visible, makes the "trick"
<div *ngFor="let item of obs$ | async; let i = index">
<div
#card
[ngStyle]="pos[i] || null"
[style.visibility]="i <= count ? 'visible' : 'hidden'"
[@move]="count == i"
(@move.done)="animationDone(count == i ? 1 : 0)"
>
{{ item }}
</div>
You can see in this stackblitz
NOTE: See this "strange" [@move.done]="animationDone(count == i ? 1 : 0)"
, only pass to the function 1 when count==i, else Angular execute so many times elements has the observable