Home > front end >  Animate individual observable elements from another component position
Animate individual observable elements from another component position

Time:11-09

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

enter image description here

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

  • Related