Angular 5 Animations - переход роутера по истории браузера назад - PullRequest
0 голосов
/ 03 мая 2018

Я пытаюсь настроить анимацию маршрутизатора, которая скользит в одном направлении, когда пользователь нажимает на любой [routerLink], но когда пользователь запускает history.back (), нажимая на кнопку внутри страницы или когда они нажимают на кнопку возврата браузера, я хочу, чтобы анимация шла в противоположном направлении.

Это решение, которое я получил до сих пор.

Основной компонент HTML

<div class="inicio" [@routerTransition]="getState(o)" (@routerTransition.start)="animationStarted($event)" (@routerTransition.done)="animationDone($event)">
    <router-outlet #o="outlet"></router-outlet>
</div>

Главный компонент TS

getState(outlet: RouterOutlet) {
    let state: number = this.appRouterState.getState(outlet.activatedRouteData.state);
    return state;
}

Это возвращает состояние ++, когда пользователь идет вперед, или состояние-- когда пользователь идет назад

Настройка запуска анимации

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 })
        ])
    ])
]);

Служба государственного контроля

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 .: работает переход "void => *" и работает ": increment", проблема заключается в том, что пользователь возвращается назад, хотя состояние изменяется, и компонент загружается без проблем, анимация не работает спусковой крючок.

Ткс за помощь.

Ответы [ 2 ]

0 голосов
/ 15 мая 2019

Только головы до тех, кто прибыл сюда. Решение действительно работает по состоянию на май 2019 года. Всего несколько исправлений и напоминаний.

  1. В классе главных компонентов this.lastState должно быть this.lastPage
  2. В вашем файле маршрутов обязательно добавьте данные {state: 'PATH_NAME'}. Код нужен для перекрестной проверки истории навигации, сохраненной в сервисе.

Кроме этого, если вы использовали правильный синтаксис и добавили анимацию в свой div-конвертер маршрутизатора-розетки, то все будет хорошо!

0 голосов
/ 03 мая 2018

Мне удалось решить проблему. Так что для тех, кто нуждается в подобном решении здесь идет:

Шаблон основного компонента

<div class="inicio" [@routerTransition]="getState(o)">
    <router-outlet #o="outlet"></router-outlet>
</div>

Класс основных компонентов

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;
}

Служба истории управления навигацией

    @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";
    }
}

Настройка анимации

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 })
            ])
        ])
    ]);
}
...