Ich versuche einige Routenänderungen in Angular zu animieren. Die Animation sollte in der Höhe zwischen nichts und der Höhe des Inhalts animieren. Dies funktioniert sehr gut, wenn der Inhalt im Voraus bekannt ist, siehe diese Plunkr: http://plnkr.co/edit/FOZSZOJaSpLbrs2vl6KaWie man angulare Animationen auf das Rendering warten lässt
Es funktioniert jedoch nicht sehr gut, in dem Moment, eine HTTP-Anfrage muss passieren. Siehe dieses plunkr: http://plnkr.co/edit/vyobBtb5KDO7nkYLLsto (Hier wurde die HTTP-Anfrage mit einem verzögerten RX-Vorgang simuliert)
Ich wäre völlig in Ordnung mit der Animation nicht gestartet, bis Inhalt geladen wurde, aber ich bezweifle, dass das möglich ist.
Was ich vermute, ist falsch, ist, dass Angular misst die Höhe der "twoComponent" rechts, wenn es eingefügt wird, aber bevor es fertig geladen hat, was dann dies verursacht.
Insgesamt nicht richtig funktioniert 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 {}
Sie einen Resolver auf die Route hinzufügen könnte, die den Inhalt lädt, bevor die Routenänderung geschieht: https://angular.io/api/router/Resolve –