Angular 2 "slide in animation" of a routed component
Solution 1
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
Solution 2
In terms of sliding in it is quite straightforward.
You can reference to the Official Angular 2 Animate docs.
You can also check out this Plunker I did for a simple showcase, using the new router v3
Bear in mind that I am struggling to figure out how to actually have the leave/exit/void transitions when the triggered element is about to be destroyed from the view.
I opened another thread in Angular 2 Animate - No visible effect of the '* => void' transition when changing routes/components to try to figure out how to make router take notice of the leaving animation/transition time.
@Component({
selector: 'home',
directives: [ROUTER_DIRECTIVES],
template: `
<div @flyInOut="'active'" class="radibre">
</div>
`,
styles: ['.radibre { width: 200px; height: 100px; background: red; }'],
animations: [
trigger('flyInOut', [
state('in', style({transform: 'translateX(0)'})),
transition('void => *', [
style({transform: 'translateX(-100%)'}),
animate(100)
]),
transition('* => void', [
animate(100, style({transform: 'translateX(100%)'}))
])
])
]
})
export class Home {
constructor() { }
}
@Component({
selector: 'page',
template: `
<div @testingBottom="'active'" class="page"></div>`,
styles: ['.page { width: 300px; height: 50px; background: green; }'],
animations: [
trigger('testingBottom', [
state('active', style({transform: 'scale(1)'})),
transition('void => *', [
style({transform: 'scale(0)'}),
animate(100)
]),
transition('* => void', [
animate(100, style({transform: 'scale(0)'}))
])
])
]
})
![Han Che](https://i.stack.imgur.com/4OVlG.jpg?s=256&g=1)
Han Che
Updated on June 21, 2020Comments
-
Han Che about 4 years
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!
-
msanford over 7 yearsA friendly note that, currently, the Plunker does not animate the transition (perhaps because of updates to angular2 from rc_ to stable?)
-
David Alsh almost 7 yearsI can't seem to build my Angular project after doing this. It seems the github project can't build at all out of the box either
-
SpaceFozzy almost 7 yearsHmm, was just able to clone, build and run the github project out of the box on two different laptops. If you're still having trouble, can you create a new question and post some code or post your project? Would love to help.
-
David Alsh almost 7 yearsHey thanks for the response, this is what happens on my computer with the latest angular CLI & node if I run
ng build --aot --prod
. i.imgur.com/kp8mrVo.jpg -
dale almost 7 yearsThis will not work for --prod builds. There is a fix in but we'll have to wait for the release: github.com/angular/angular/issues/17467
-
Evgeny Bobkin over 6 yearsBut, how to animate transition between "products/id1" and "products/id2" ? It does not look like there is a transition defined for that case.
-
Mark over 6 yearsThere has to be away to do this without hardcoding CSS values in TypeScript, like maybe listening to a 'animationEnd' on a element. I get animate might help a bunch pin a bunch of animations together like GSAP but I thought we weren't doing CSS animations in JavaScript anymore.
-
user1059939 almost 6 yearsJust a quick note that
products
is re-used by default. You need to supply aRouteReuseStrategy
which tells Angular to create multipleproduct
then you can animate them. However the rest of Animation is as cryptic as you say