Angular 5 Animations - 浏览器历史记录中的路由器转换

时间:2018-05-03 11:58:45

标签: animation routing angular5 transition

我正在尝试设置一个路由器动画,当用户点击任何[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 =&gt; *”转换正在运行,“:increment”也正常工作,问题出在用户倒退时,虽然状态发生变化且组件加载没有问题动画不会触发器。

请求帮助。

2 个答案:

答案 0 :(得分:0)

我设法解决了这个问题。所以对于那些需要类似解决方案的人来说:

主要组件模板

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

答案 1 :(得分:0)

仅对那些到达这里的人有所提示。该解决方案自2019年5月起生效。只需进行一些更正和提醒。

  1. 在主组件类中,this.lastState应为this.lastPage
  2. 在路由文件中,请确保添加数据{state:'PATH_NAME'}。代码需要使用它来交叉检查服务中保存的导航历史记录。

除此之外,只要您使用了正确的语法并将动画添加到路由器出口包装div中,那么您就可以开始使用了!