The app I am working on requires the ability to navigate back and forth through the routes so when you navigate one way through the app in one direction the components animate from left to right, and when you navigate back they navigate from right to left.
i.e.
component1 -> component2 = left -> right animation
component2 -> component1 = right -> left animation
I can achieve this easily enough in NG4 but the issue is that it doesn't navigate both the exit and entering components. The exiting component just disappears and the entering component animates in.
I can also achieve this in NG2 - but the complication arises when you have conditional animation. ie.
component2 -> component3 = left -> right animation
component2 -> component1 = right -> left animation
The problem here is triggering a different animation depending on the next or previous route.
Does anyone have a solution in either NG2 or 4 to solve the issue of animating both views simultaneously in either direction?
I haven't put this in plunkr because I have no idea how to set up an NG4 app in that. Apologies.
My NG4 solution is based on this demo app https://github.com/matsko/ng4-animations-preview
but essentially in my app.component.ts I have the following animation:
animations: [
trigger('routerAnimations',[
transition('page1 => page2',[
style({transform: 'translateX(100%)'}),
animate('500ms')
]),
transition('page2 => page1', [
style({transform: 'translateX(-100%)'}),
animate('500ms')
]),
transition('page2 => page3',[
style({transform: 'translateX(100%)'}),
animate('500ms')
]),
transition('page3 => page2',[
style({transform: 'translateX(-100%)'}),
animate('500ms')
]),
transition('page3 => page4',[
style({transform: 'translateX(100%)'}),
animate('500ms')
]),
transition('page4 => page3',[
style({transform: 'translateX(-100%)'}),
animate('500ms')
])
])
]
and a function that grabs an animation value from each route and binds (?) it to the outlet variable on the <router-outlet> in app.component.html
:
export class AppComponent {
prepareRouteTransition(outlet) {
let routeData: any;
try {
routeData = outlet['_activatedRoute'].snapshot.routeConfig['animation'];
} catch(e) {
return '';
}
return routeData.value;
}
}
Function above grabs the animation value which is used in the animation to define the transition start and end values:
export const APP_ROUTES = [{
path: '',
component: Page1Component,
animation: {
value: 'page1',
}
},
{
path: 'page2',
component: Page2Component,
animation: {
value: 'page2',
}
},
{
path: 'page3',
component: Page3Component,
animation: {
value: 'page3'
}
},
{
path: 'page4',
component: Page4Component,
animation: {
value: 'page4'
}
}
];
app.component.html:
<div class="page" [@routerAnimations]="prepareRouteTransition(outlet)">
<router-outlet #outlet="outlet"></router-outlet>
</div>
In the component file, set the trigger that defines the animations as the value of the animations: property in the @Component() decorator. In the HTML template file, use the trigger name to attach the defined animations to the HTML element to be animated.
Enable routing transition animationlink The Angular router comes with high-level animation functions that let you animate the transitions between views when a route changes. To produce an animation sequence when switching between routes, you need to define nested animation sequences.
The ngAnimate module adds and removes classes. The ngAnimate module does not animate your HTML elements, but when ngAnimate notice certain events, like hide or show of an HTML element, the element gets some pre-defined classes which can be used to make animations.
You can achieve this now by defining animations that query for :enter
and :leave
elements.
This example will animate out the exiting route and animate in the entering route smoothly:
const slideLeft = [
query(':leave', style({ position: 'absolute', left: 0, right: 0 ,transform: 'translate3d(0%,0,0)' })),
query(':enter', style({ position: 'absolute', left: 0, right: 0, transform: 'translate3d(-100%,0,0)' })),
group([
query(':leave',
animate('1s', style({ transform: 'translate3d(100%,0,0)' }))),
query(':enter',
animate('1s', style({ transform: 'translate3d(0%,0,0)' })))
])
]
const slideRight = [
query(':leave', style({ position: 'absolute', left: 0, right: 0 , transform: 'translate3d(0%,0,0)'})),
query(':enter', style({ position: 'absolute', left: 0, right: 0, transform: 'translate3d(100%,0,0)'})),
group([
query(':leave',
animate('1s', style({ transform: 'translate3d(-100%,0,0)' }))),
query(':enter',
animate('1s', style({ transform: 'translate3d(0%,0,0)' })))
])
]
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
animations: [
trigger('routerAnimations', [
transition('products => product-details', slideRight),
transition('product-details => products', slideLeft)
])
]
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With