简体   繁体   English

如何使Angular动画等待渲染完成

[英]How to make Angular animations wait for rendering to finish

I'm trying to animate some route changes in Angular. 我正在尝试为Angular中的某些路线变化设置动画。 The animation should height animate between nothing and the height of the content. 动画的高度应在没有内容和内容的高度之间设置动画。 This works very well when the content is known ahead of time, see this plunkr: http://plnkr.co/edit/FOZSZOJaSpLbrs2vl6Ka 如果提前知道该内容,则效果很好,请参见以下代码: http ://plnkr.co/edit/FOZSZOJaSpLbrs2vl6Ka

It does however not work very well, the moment an http request has to happen. 但是,当必须发出http请求时,它不能很好地工作。 See this plunkr: http://plnkr.co/edit/vyobBtb5KDO7nkYLLsto (Here the http request has been simulated by using a delayed rx operation) 请参阅以下代码: http ://plnkr.co/edit/vyobBtb5KDO7nkYLLsto(此处使用延迟rx操作模拟了http请求)

I would be perfectly fine with the animation not starting until content has been loaded, but i doubt that is possible. 我会完全满意动画,直到内容加载完毕才开始,但是我怀疑这是可能的。

What i assume is going wrong, is that Angular is measuring the height of the "twoComponent" right when it's inserted, but before it has finished loading, which then causes this. 我认为出了问题,是Angular在“ twoComponent”插入时但在完成加载之前正在测量“ twoComponent”的高度,这会导致这种情况。

Overall not correctly working code: 总体上不能正常工作的代码:

//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 {}

Use a Resolver: Demo 使用解析器: 演示

Resolver 分解器

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 的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 {}

Two Component 两部分

@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);
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM