如何制作Angular动画等待渲染完成

时间:2017-12-16 20:34:43

标签: angular animation angular-animations

我试图在Angular中设置一些路线变化的动画。动画应该在任何内容和内容的高度之间设置高度动画。当内容提前知道时,这非常有效,请参阅此plunkr:http://plnkr.co/edit/FOZSZOJaSpLbrs2vl6Ka

然而,当http请求发生时,它确实不能很好地工作。请参阅此plunkr:http://plnkr.co/edit/vyobBtb5KDO7nkYLLsto(这里使用延迟的rx操作模拟了http请求)

如果动画在内容加载之前没有开始,我会完全没问题,但我怀疑这是可能的。

我认为是错误的,是Angular正在测量" twoComponent"当它被插入时,但在它完成加载之前,然后导致这一点。

总体上没有正确使用代码:

//our root app component
import {Component, NgModule, VERSION} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {RouterModule, Routes} from '@angular/router';
import {HashLocationStrategy} from '@angular/common';
import {animate, animateChild, query, style, transition, trigger} from '@angular/animations';
import {Observable} from 'rxjs/Observable';
import {of} from 'rxjs/observable/of';
import 'rxjs/add/operator/delay';

@Component({
  selector: 'my-app',
  template: `
    <div>
      <h2>Hello {{name}}</h2>
      <a routerLink="">Go to one</a>
      <a routerLink="two">Go to two</a>
      <div [@routeAnimations]="prepareRoute(outlet)" 
            style="background-color:pink"
            id="main-router-outlet">
        <router-outlet #outlet="outlet"></router-outlet>
      </div>
    </div>
  `,
  animations: [
    trigger('routeAnimations', [
      transition('* => *', [
        query(':enter', [
          style({height: 0, opacity: 0, width: 0}),
        ], {optional: true}),
        query(':leave', [
          style({height: '*', width: '*'}),
          animate('200ms', style({opacity: 0})),
          animate('500ms', style({height: 0, width: 0})),
        ], {optional: true}),
        query(':enter', [
          animate('500ms', style({height: '*', width: '*'})),
          animate('500ms', style({opacity: 1})),
          animateChild(),
        ], {optional: true}),
      ]),
    ]),
  ],
  styles: [
    `#main-router-outlet ::ng-deep > * {
        display: block;
      } `
    ]
})
export class App {
  name:string;
  constructor() {
    this.name = `Angular! v${VERSION.full}`
  }

  public prepareRoute(outlet: RouterOutlet) {
    return outlet.activatedRouteData['animation'] || '';
  }
}

@Component({
  template: `one component<br>more`
})
export class oneComponent {

}


@Component({
  template: `two component
  <div *ngFor="let s of dynamicContent|async">
  {{s}}
  </div>
  `
})
export class twoComponent {
  public dynamicContent: Observable<string[]>;

  ngOnInit() {
    this.dynamicContent = of(['foo', 'bar', 'baz'])
      .delay(200);
  }
}

@NgModule({
  imports: [ 
    BrowserModule, 
    BrowserAnimationsModule,
    RouterModule.forRoot([{
      path: '',
      component: oneComponent,
    data: {
      animation: 'one',
    }
    },
    {
      path: 'two',
      component: twoComponent,
    data: {
      animation: 'two',
    }
    }],  { useClass: HashLocationStrategy })
    ],
  declarations: [ App, oneComponent, twoComponent ],
  bootstrap: [ App ]
})
export class AppModule {}

1 个答案:

答案 0 :(得分:3)

使用解析器: Demo

<强>解析器

import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot,ActivatedRoute } from '@angular/router';
import { ContactsService } from './contacts.service';

@Injectable()
export class ArrResolve implements Resolve<string[]> {

  constructor() {}

  resolve(route: ActivatedRouteSnapshot) {
    return  of(['foo', 'bar', 'baz'])
      .delay(200);
  }
}

<强>的AppModule

@NgModule({
  imports: [ 
    BrowserModule, 
    BrowserAnimationsModule,
    RouterModule.forRoot([{
      path: '',
      component: oneComponent,
    data: {
      animation: 'one',
    }
    },
    {
      path: 'two',
      component: twoComponent,
    data: {
      animation: 'two',
    },
    resolve: {
      arr: ArrResolve  
    }
    }],  { useClass: HashLocationStrategy })
    ],
  declarations: [ App, oneComponent, twoComponent ],
  bootstrap: [ App ],
  providers: [ArrResolve]
})
export class AppModule {}

两个组件

@Component({
  template: `two component
  <div *ngFor="let s of dynamicContent|async">
  {{s}}
  </div>
  `
})
export class twoComponent {
  public dynamicContent: Observable<string[]>;
  constructor(private route:ActivatedRoute) {

  }

  ngOnInit() {
    this.dynamicContent = of(this.route.snapshot.data.arr);
  }
}