Reputation: 11
I'm trying to setup a router animation that slides in one direction when the user click on any [routerLink], but when the user triggers a history.back() clicking in a button inside the page or when they click on the browser back button, I want the animation to go on the opposite direction.
This is the solution I got so far.
Main Component Html
<div class="inicio" [@routerTransition]="getState(o)" (@routerTransition.start)="animationStarted($event)" (@routerTransition.done)="animationDone($event)">
<router-outlet #o="outlet"></router-outlet>
</div>
Main Component TS
getState(outlet: RouterOutlet) {
let state: number = this.appRouterState.getState(outlet.activatedRouteData.state);
return state;
}
This is returning state++ when the user goes forward or state-- when the user goes backward
Animation Trigger Setup
return trigger('routerTransition', [
transition('void => *', [
query(':enter, :leave', style({ position: 'fixed', width: '100%', height: "100%" }), { optional: true }),
group([
query(':enter', [style({ transform: 'translateX(-100%)' }), animate('0.5s ease-in-out', style({ transform: 'translateX(0%)' }))], { optional: true }),
query(':leave', [style({ transform: 'translateX(0%)' }), animate('0.5s ease-in-out', style({ transform: 'translateX(100%)' }))], { optional: true })
])
]),
transition(':increment', [
query(':enter, :leave', style({ position: 'fixed', width: '100%', height: "100%" }), { optional: true }),
group([
query(':enter', [style({ transform: 'translateX(-100%)' }), animate('0.5s ease-in-out', style({ transform: 'translateX(0%)' }))], { optional: true }),
query(':leave', [style({ transform: 'translateX(0%)' }), animate('0.5s ease-in-out', style({ transform: 'translateX(100%)' }))], { optional: true })
])
]),
transition(':decrement', [
query(':enter, :leave', style({ position: 'fixed', width: '100%', height: "100%" }), { optional: true }),
group([
query(':enter', [style({ transform: 'translateX(100%)' }), animate('0.5s ease-in-out', style({ transform: 'translateX(0%)' }))], { optional: true }),
query(':leave', [style({ transform: 'translateX(0%)' }), animate('0.5s ease-in-out', style({ transform: 'translateX(-100%)' }))], { optional: true })
])
])
]);
State control service
export interface ItemHistorico {
index: number;
url: string;
}
@Injectable()
export class AppRouterState {
private lastIndex: number = 0;
private isBack: boolean = false;
private historico: ItemHistorico[] = [];
constructor(private router: Router, private menuService: MenuService) { }
public loadRouting(): void {
this.router.events.filter(event => event instanceof NavigationEnd).subscribe(({ urlAfterRedirects }: NavigationEnd) => {
if (urlAfterRedirects !== "/") {
let last: ItemHistorico = _.maxBy(this.historico, h => h.index);
let max: number = last ? last.index : 1;
let next = max + 1;
this.historico = [...this.historico, { index: next, url: urlAfterRedirects }];
if (!this.isBack) {
this.lastIndex++;
}
else {
this.isBack = false;
}
}
else {
this.menuService.obterPaginaInicial().subscribe(menuItem => {
let url = menuItem.url;
this.router.navigate([`/${url}`]);
});
}
});
window.onpopstate = ev => {
let hash: string = (ev.currentTarget as Window).location.hash;
if (hash === "#/") {
this.isBack = false;
}
else {
this.isBack = true;
this.lastIndex--;
}
};
}
public getHistory(): ItemHistorico[] {
return this.historico;
}
public getState(current: string): number {
return this.lastIndex;
}
public getIsBack(): boolean {
return this.isBack;
}
}
Obs.: The "void=>*" transition is working and the ":increment" is also working, the problem lies when the user goes backwards, although the state changes and the component loads without problems the animation don't trigger.
Tks for the help.
Upvotes: 0
Views: 1754
Reputation: 400
Just a heads up to those who arrived here. The solution does work as of May 2019. Just a few corrections and reminders to be made.
Other than that, as long as you've used the correct syntax and added the animations to your router-outlet wrapper div then you should be good to go!
Upvotes: 0
Reputation: 11
I manage to resolve the problem. So for anyone who needs a similar solution here goes:
Main Component Template
<div class="inicio" [@routerTransition]="getState(o)">
<router-outlet #o="outlet"></router-outlet>
</div>
Main Component Class
currentState: number = 0;
lastPage: string;
getState(outlet: RouterOutlet) {
let state: string = outlet.activatedRouteData.state;
if (this.lastState !== state) {
let dir: string = this.appRouterState.getDirection(state);
if (dir === "f") {
this.currentState++;
}
else {
this.currentState--;
}
this.lastPage= state;
}
return this.currentState;
}
History navigation control service
@Injectable()
export class AppRouterState {
private history: string[] = [];
private isBack: boolean;
constructor(private router: Router) { }
public loadRouting(): void {
this.router.events.filter(event => event instanceof NavigationEnd).subscribe(({ urlAfterRedirects }: NavigationEnd) => {
this.history= [...this.history, urlAfterRedirects ];
});
window.onpopstate = ev => {
this.isBack = true;
};
}
public getHistory(): string[] {
return this.history;
}
public getDirection(page: string): string {
if (this.isBack) {
if (`/${page}` === this.history[this.history.length - 3]) {
this.history.splice(this.history.length - 2, 2);
this.isBack = false;
return "b";
}
}
return "f";
}
}
Animation setup
export function routerTransition() {
return trigger('routerTransition', [
transition(':increment', [
query(':enter, :leave', style({ position: 'fixed', width: '100%', height: "100%" }), { optional: true }),
group([
query(':enter', [style({ transform: 'translateX(100%)' }), animate('0.5s ease-in-out', style({ transform: 'translateX(0%)' }))], { optional: true }),
query(':leave', [style({ transform: 'translateX(0%)' }), animate('0.5s ease-in-out', style({ transform: 'translateX(-100%)' }))], { optional: true })
])
]),
transition(':decrement', [
query(':enter, :leave', style({ position: 'fixed', width: '100%', height: "100%" }), { optional: true }),
group([
query(':enter', [style({ transform: 'translateX(-100%)' }), animate('0.5s ease-in-out', style({ transform: 'translateX(0%)' }))], { optional: true }),
query(':leave', [style({ transform: 'translateX(0%)' }), animate('0.5s ease-in-out', style({ transform: 'translateX(100%)' }))], { optional: true })
])
])
]);
}
Upvotes: 1