如何在Angular中为* ngFor设置动画?

时间:2016-05-13 18:49:00

标签: angular transition angular-animations

我需要在填充和显示ngFor列表时设置动画。每个元素都应该有一个转换,让我们说something like this

我该怎么做?

2 个答案:

答案 0 :(得分:12)

它存在一些问题,因为ngFor会执行一些冗余的添加/删除操作,这会导致项目无法设置动画,但不应该:

import {Component} from 'angular2/core';
import { Component, Directive, OnDestroy, Input } from 'angular2/core';

@Component({
    selector: 'my-app',
    template: `<div (click)="$event.preventDefault()">
        <button type="button" (click)="pushItem()">Push</button>
        <button type="button" (click)="removeItemLast()">Remove Last</button><br/>
        <button type="button" (click)="unshiftItem()">Unshift</button>
        <button type="button" (click)="removeItemFirst()">Remove First</button><br/>
        <ul>
          <li class="my-animation" *ngFor="#item of items">
            {{item.title}}
          </li>
        </ul>
      </div>`
})
export class AppComponent {
  private count:number = 1;
  public items: Array<any>;
  constructor() { 
    console.clear(); 
    this.items = [];
    this.items.push(this.newItem());
    this.items.push(this.newItem());
    }
    pushItem() {
        this.items.push(this.newItem());
    },
    removeItemLast() {
      if(this.items.length > 0) this.items.splice(this.items.length - 1, 1);
    },
    unshiftItem() {
        this.items.unshift(this.newItem());
    },
    removeItemFirst() {
      if(this.items.length > 0) this.items.splice(0, 1);
    },
    newItem() {
      return {title: 'Item' + this.count++};
    }

}
@keyframes MyAnimation {
  0% {
    padding-left: 100px;
  }
  100% {
    padding-left: 0px;
  } 
}

.my-animation {
  animation: MyAnimation 1s;
}
<{3}}中的

Plunker example (RC.x) 表明了这个问题。

<强>更新

这是很久以前修复的

工作 https://github.com/angular/angular/issues/7239

答案 1 :(得分:6)

现在有guide to Angular's animation system。如果我们想要做一些奇特的事情,这会有所帮助,比如只在元素初始化后添加元素的动画,而不是已经存在的元素。我已经修改了之前的答案,以Angular 2的方式进行。

Plunker:http://plnkr.co/edit/NAs05FiAVTlUjDOZfEsF?p=preview

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

@Component({
    selector : 'my-app',
    animations: [
        trigger('growShrinkStaticStart', [
            state('in', style({ height: '*', 'padding-top': '*', 'padding-bottom': '*', 'margin-top': '*', 'margin-bottom': '*' })),
            transition('* => void', [
                style({ height: '*', 'padding-top': '*', 'padding-bottom': '*', 'margin-top': '*', 'margin-bottom': '*' }),
                animate("0.5s ease", style({ height: '0', 'padding-top': '0', 'padding-bottom': '0', 'margin-top': '0', 'margin-bottom': '0' }))
            ]),
            transition('void => false', [
                /*no transition on first load*/
            ]),
            transition('void => *', [
                style({ height: '0', 'padding-top': '0', 'padding-bottom': '0', 'margin-top': '0', 'margin-bottom': '0' }),
                animate("0.5s ease", style({ height: '*', 'padding-top': '*', 'padding-bottom': '*', 'margin-top': '*', 'margin-bottom': '*' }))
            ])
        ])
    ],
    template : `<div (click)="$event.preventDefault()">
        <button type="button" (click)="pushItem()">Push</button>
        <button type="button" (click)="removeItemLast()">Remove Last</button><br/>
        <button type="button" (click)="unshiftItem()">Unshift</button>
        <button type="button" (click)="removeItemFirst()">Remove First</button><br/>
        <ul style="background: light-blue">
          <li *ngFor="let item of items" 
          [@growShrinkStaticStart]="animationInitialized.toString()" 
          (@growShrinkStaticStart.done)="animationInitialized = true"
          style="background-color:pink; border:1px dashed gray; overflow:hidden">
            <h3>{{item.title}}</h3><p>{{item.description}}</p>
          </li>
        </ul>
        <div>Footer</div>
      </div>`
})
export class AppComponent
{
    private count: number = 1;
    public items: Array <{ title: string, description: string }> ;
    private animationInitialized: boolean = false;

    constructor() {
        this.items = [];
        this.items.push(this.newItem());
        this.items.push(this.newItem());
    }

    pushItem() {
        this.items.push(this.newItem());
    }

    removeItemLast() {
        if (this.items.length > 0)
            this.items.splice(this.items.length - 1, 1);
    }

    unshiftItem() {
        this.items.unshift(this.newItem());
    }

    removeItemFirst() {
        if (this.items.length > 0)
            this.items.splice(0, 1);
    }

    newItem() {
        let d: string = "";
        let possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZ    abcdefghijklmnopqrstuvwxyz0123456789 . ! ? ";

        for (let i = 0; i < Math.floor(Math.random() * 50000); i++)
            d += possible.charAt(Math.floor(Math.random() * possible.length));

        return { title : 'Item' + this.count++, description: d };
    }
}