let's say I have 2 routed components and two Routerlinks in the fixed navbar to route them. I want them to slide in from the right when I click the Routerlinks.
I don't want to offset the component with css and use a timeout function to change the css class to let it slide in (e.g. with ngStyle or ngClass).
are there any more elegant ways do achieve that in Angular 2?
Thanks!
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