5

I've been digging around the Angular2 documentation and there doesn't seem to be a simple way to add delays to animations. For reference, here is what I'm aiming to achieve: plunkr using jQuery

I want to use Angular2's animation features though since these "bars" are being generated within a loop. They animate fine, but all at once. I want to stagger them by 1s increments. Here's my main component file:

import {
  Component,
  Input,
  trigger,
  state,
  style,
  transition,
  animate
} from '@angular/core';


export class Skill {
  skill: string;
  level: number;
}

const SKILLS: Skill[] = [
    { skill: 'x', level: 70 },
    { skill: 'y', level: 100 },
    { skill: 'z', level: 80 }
]

@Component({
  selector: 'app-wrap',
  template: `
    <div *ngFor="let skill of skills; let i = index" class="skill">
      <span class="bar" [style.width.%]="skill.level" [@expandSkill]>&nbsp;</span>
    </div>
  `,
  animations: [
    trigger('expandSkill', [
      state('in', style({ width: 'auto' })),
      transition('void => *', [
        style({ width: '0' }),
        animate('1000ms ease-in-out')
      ])
    ]
  ]
})

export class AppComponent {
  skills = SKILLS;
}

I came across this other SO question that seems similar, but it was asked several months ago, before the final release.

Community
  • 1
  • 1
itsclarke
  • 8,622
  • 6
  • 33
  • 50

3 Answers3

8

After hammering my head against the animation DSL to make staggering animations a thing. I found an alternative way of doing animations which allows staggering!

The trick is to have a directive responsible of the animation using the Renderer and Service to hold your animation store!

Directive important code

this.animation = this.renderer.animate(
  this.element.nativeElement.firstElementChild || this.element.nativeElement,
  this.animService.getAnimation(animationName).startingStyles,
  this.animService.getAnimation(animationName).keyframes,
  this.duration,
  this.delay,
  this.easing
);
this.animation.pause();
this.animation.play();

How to use it in template

<div *ngFor="let str of ['foo','bar','baz']; let i = index"
  anim-aes
  [anim-aes-delay]="i*200"
  [anim-aes-duration]="500"
  [anim-aes-animation]="'fadeIn'"
  [anim-aes-animation-leave]="'fadeOut'"
  [anim-aes-play]="show">
  click {{str}}
</div>

I made a working plunkr with everything you need!

plunkr

Aesdotjs
  • 192
  • 1
  • 9
  • Just noticed it's not working anymore(probably an angular 2 update which changed some things) gonna look what i can do! thanks for the feedback – Aesdotjs May 14 '17 at 13:21
  • This method doesn't work with angular 4 :(((( See this post https://github.com/angular/angular/issues/15294 – Aesdotjs May 14 '17 at 13:30
8

Since Angular 4.2.6 you can use query(), stagger() and animateChild() to stagger all kinds of animations. Here's an example:

template: `
    <div [@stagger]>
      <div [@fade] *ngFor="let item of items;">{{item}}</div>
    </div>
  `,
animations: [
    trigger('fade', [
      transition(':enter', [style({opacity: 0}), animate('.6s ease')])
    ]),
    trigger('stagger', [
      transition(':enter', [
        query(':enter', stagger('.3s', [animateChild()]))
      ])
    ])
  ]

Plunker: https://embed.plnkr.co/pQQSZETi7mnToB6lqfID/

Martin Cremer
  • 5,191
  • 2
  • 32
  • 38
1

The staggering module is still not ready. But there are some hacky paths to archieve the same effect.

  1. If you have a fixed list in size (or at least at screen). You can write a stagger function that returns a delayed animation for every state throught 0 to n. the stagger function should return AnimationEntryMetadata[] Then. you should pass bind the @expandSkill to the variable i on the loop. On the end, you will be creating dynamic, in animations for every object.

  2. Another option you have, is use, the Renderer plus a ViewChildren, query the childs, and create the stagger animation with css styles. The renderer provides a setElementStyle.

  3. There is a thirth option, a little more hacky.. Render a new list, an populate it throught a setTimeout.

I used the two for some rich animations. Sure there are better aproaches :)

jordic
  • 51
  • 1
  • 3