With Angular 4.1 it is now possible to create specific route animations. This is different from triggering an animation when a component is displayed because it will let you animate the entering/leaving component at the same time for a smooth transition, and let you modify the transition depending on which component is coming or going. That means you can do complex transitions like slide a component in from the right if you’re drilling down into content, and slide it in from the left if you’re entering it via a ‘back’ button from another component.
-
First, annotate your router outlet like so (eg.
app.component.html
):<div class="page" [@routerAnimations]="prepareRouteTransition(outlet)"> <router-outlet #outlet="outlet"></router-outlet> </div>
-
Implement the
prepareRouteTransition(outlet)
function in the corresponding component definition (e.g.app.component.js
).prepareRouteTransition(outlet) { const animation = outlet.activatedRouteData['animation'] || {}; return animation['value'] || null; }
-
Define your animations (e.g.
app.component.js
):const slideLeft = [ query(':leave', style({ position: 'absolute', left: 0, right: 0 ,transform: 'translate3d(0%,0,0)' }), {optional:true}), query(':enter', style({ position: 'absolute', left: 0, right: 0, transform: 'translate3d(-100%,0,0)' }), {optional:true}), group([ query(':leave', group([ animate('500ms cubic-bezier(.35,0,.25,1)', style({ transform: 'translate3d(100%,0,0)' })), // y: '-100%' ]), {optional:true}), query(':enter', group([ animate('500ms cubic-bezier(.35,0,.25,1)', style({ transform: 'translate3d(0%,0,0)' })), ]), {optional:true}) ]) ] const slideRight = [ query(':leave', style({ position: 'absolute', left: 0, right: 0 , transform: 'translate3d(0%,0,0)'}), {optional:true}), query(':enter', style({ position: 'absolute', left: 0, right: 0, transform: 'translate3d(100%,0,0)'}), {optional:true}), group([ query(':leave', group([ animate('500ms cubic-bezier(.35,0,.25,1)', style({ transform: 'translate3d(-100%,0,0)' })), // y: '-100%' ]), {optional:true}), query(':enter', group([ animate('500ms cubic-bezier(.35,0,.25,1)', style({ transform: 'translate3d(0%,0,0)' })), ]), {optional:true}) ]) ]
-
Add the animation metadata to your route definitions (e.g.
app.routing.ts
):const routes: Routes = [ { path: 'products', component: ProductsComponent, data: { animation: { value: 'products', } } }, { path: 'products/:id', component: ProductDetailComponent, data: { animation: { value: 'product-detail', } } }
-
Finally, register a ‘routerAnimations’ animation trigger on your component with the animations and route metadata you defined (e.g.
app.component.js
):@Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], animations: [ trigger('routerAnimations', [ transition('products => product-detail', slideRight), transition('product-detail => products', slideLeft), ]) ] })
Don’t forget to polyfill the Web Animation API to target old browsers
Matias Niemela talks more about route animations at ng-conf here (with a demo): https://youtu.be/Oh9wj-1p2BM?t=12m21s
His presentation code: https://github.com/matsko/ng4-animations-preview