Angular 2 - router: How to animate page transition

2019-06-04 00:50发布

问题:

Currently inside my NG2 app I'm using a resolver, that makes a connection to signalr.
I have configured the resolver inside my route config, so when navigation to the destination page, the resolve function is called accordingly.

I've managed to show an animation when the destination page is initialized.

However, I would like to show an 'is-busy' like animation DURING the resolving of my resolver, but I don't know how to do this. Any suggestions?

This is my current setup:

//resolver.ts
@Injectable()
export class ConnectionResolver implements Resolve<SignalRConnectionMock> {

constructor(private _signalR: SignalR) {}

   resolve() {
      console.log('HomeRouteResolver. Resolving...');
      return new SignalRConnectionMock();// this._signalR.connect();
   }
}

//inside route.ts
{ path: 'docs', 
  component: DocumentationComponent, 
  resolve: { connection: ConnectionResolver }
}

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

//router.transition.ts
export function routerTransition() {
   return slideToLeft();
}

function slideToLeft() {
  return trigger('routerTransition', [
    state('void', style({position: 'fixed', width: '100%'}) ),
    state('*', style({position: 'fixed', width: '100%'}) ),
    transition(':enter', [  // before 2.1: transition('void => *', [
      style({transform: 'translateX(100%)'}),
      animate('0.5s ease-in-out', style({transform: 'translateX(0%)'}))
    ]),
    transition(':leave', [  // before 2.1: transition('* => void', [
      style({transform: 'translateX(0%)'}),
       animate('0.5s ease-in-out', style({transform: 'translateX(-100%)'}))
    ])
 ]);
}

//home.component.ts
import { routerTransition } from './route.transition';

@Component({
   selector: 'home',        
   animations: [routerTransition()],
   host: {'[@routerTransition]': ''}
})
export class HomeComponent {}

回答1:

You can catch the router events! you have for example: NavigationStart NavigationEnd.

when you navigate, NavigationStart will send first, then its call the "resolve" promise and when the resolve finished. NavigationEnd will send with and your "leave" animation will start.

first you should inject "Router" inside component constructor:

import {Router} from "@angular/router";
 constructor(private router:Router){}

next you should call events Observable, you should filter events, make sure you navigate outside of 'home' state and take make sure it's happen only once :

  import {NavigationEnd, NavigationStart} from "@angular/router";
  import 'rxjs/add/operator/take';
  import 'rxjs/add/operator/filter';

   constructor(private router:Router){
     router.events.filter(e => e instanceof NavigationStart && !router.isActive("home", false) ).take(1).subscribe(() => { 
         // resolve has been call here! "is-busy"        
      }

     router.events.filter(e => e instanceof NavigationEnd && !router.isActive("home", false)).take(1).subscribe(() => { 
        // resolve finished here!  end of "is-busy" start of "leave" animation  

      }
   }

Good Luck!



回答2:

You can have a loading component in your root app component, and then listen on navigation event. Build a navigation intercepor make loading component active when navigation starts and deactive when navigation ends.

Take a look at this solution, it's probably what you want: Show loading screen when navigating between routes in Angular 2