Анимация углового маршрута меняется динамически

Я хочу динамически менять анимацию маршрута. У меня есть 4 анимации в app.component.ts, когда я нажимаю кнопку, я получу некоторое значение типа анимации в соответствии с тем, как я буду менять анимацию. Например, если я получаю 1, я буду применять slideLeft, если 2 - slideRight и так далее. Но.... но я не могу изменить анимацию маршрута динамически. Я обновляю массив анимации, но я думаю, что угловой маршрутизатор принимает значение анимации только в первый раз. после этого, даже если значение currentAnimation изменено, оно не будет обновлять анимацию.

Мой app.component.ts

import { ComponentsModelService } from './components-model.service';
import { Router, NavigationEnd, NavigationStart } from "@angular/router";
import 'rxjs/add/operator/filter';
import { Component, Directive,HostBinding, HostListener, OnInit } from '@angular/core';
import {trigger, query, transition, style, animate, state, group} from '@angular/animations';


const slideToRight = [
    query(':enter, :leave', style({ position: 'fixed', left: 0, right: 0, top: 0, bottom: 0 }),{ optional: true }),
    query(':leave', style({ transform: 'translateX(0%)' }), { optional: true }),
    query(':enter', style({ transform: 'translateX(-100%)' }),{ optional: true }),
    group([
        query(':leave', [
            animate('500ms ease-in-out', style({ transform: 'translateX(100%)' })),
        ], { optional: true }),
        query(':enter', [
            animate('500ms ease-in-out', style({ transform: 'translateX(0%)' })),
        ],{ optional: true })
    ])
];

const slideToLeft = [
    query(':enter, :leave', style({ position: 'fixed', left: 0, right: 0, top: 0, bottom: 0 }),{ optional: true }),
    query(':leave', style({ transform: 'translateX(0%)' }), { optional: true }),
    query(':enter', style({ transform: 'translateX(100%)' }),{ optional: true }),
    group([
        query(':leave', [
            animate('500ms ease-in-out', style({ transform: 'translateX(-100%)' })),
        ], { optional: true }),
        query(':enter', [
            animate('500ms ease-in-out', style({ transform: 'translateX(0%)' })),
        ],{ optional: true })
    ])
];

const slideToTop = [
    query(':enter, :leave', style({ position: 'fixed', left: 0, right: 0, top: 0, bottom: 0 }),{ optional: true }),
    query(':leave', style({ transform: 'translateY(0%)' }), { optional: true }),
    query(':enter', style({ transform: 'translateY(100%)' }),{ optional: true }),
    group([
        query(':leave', [
            animate('500ms ease-in-out', style({ transform: 'translateY(-100%)' })),
        ], { optional: true }),
        query(':enter', [
            animate('500ms ease-in-out', style({ transform: 'translateY(0%)' })),
        ],{ optional: true })
    ])
];

const slideToBottom = [
    query(':enter, :leave', style({ position: 'fixed', left: 0, right: 0, top: 0, bottom: 0 }),{ optional: true }),
    query(':leave', style({ transform: 'translateY(0%)' }), { optional: true }),
    query(':enter', style({ transform: 'translateY(-100%)' }),{ optional: true }),
    group([
        query(':leave', [
            animate('500ms ease-in-out', style({ transform: 'translateY(100%)' })),
        ], { optional: true }),
        query(':enter', [
            animate('500ms ease-in-out', style({ transform: 'translateY(0%)' })),
        ],{ optional: true })
    ])
];

var currrentAnimation = slideToTop;

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css'],
    animations: [
        trigger('routeTransition', [
            transition("* => *", currrentAnimation)
        ])
    ]
})

export class AppComponent {
    ios: boolean;
    iosClass: string = "";
    previousUrl: string: "";
    count: number = 1;
    constructor(private router: Router) {
        console.log("in contrcutore");
        this.ios = !!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform);
        if(this.ios == true) {
            this.iosClass = "ios";
        }
    }
    getState(outlet) {
       return outlet.activatedRouteData.state;
    }
    changeAnimation(){

        /* Changing animation object here but it is not working */
        console.log("button clicked2222222222");
        currrentAnimation = slideToRight;
        var navigateToPage = "page3";
        this.router.navigate([navigateToPage]);
    }
};

app.component.html

<link href="https://fonts.googleapis.com/css?family=Roboto:100i" rel="stylesheet">
<!-- use the font -->
<style>
body {
    font-family: 'Maven Pro', sans-serif;
}
html, body,
main {
    position: relative;
    width: 100%;
    height: 100%;
}

</style>
<main [@routeTransition]="getState(o)">
    <router-outlet  #o="outlet"></router-outlet>
</main>
<button (click) ="changeAnimation()">Change Animation</button>

Теперь на changeAnimation я обновляю currentAnimation до slideToRight, но при изменении маршрута работает slideToTop. Я не могу понять, почему changeAnimation не меняет анимацию.

Обновление: я решил это

Динамическое обновление массива анимации не решит проблему. Перед ответом вам необходимо понять, как работает угловая анимация маршрута.

1- переход ("* => *", currrentAnimation), который вы видите * => * означает, что если у вас есть два маршрута, скажем 'route1' и 'route2', тогда * будет указывать любой из них, например, 'route1 => route2' и * будет применять анимацию, если маршруты разные *(обратите внимание). Переменные 'route1' и 'route2' вычисляются в функции getState:

getState(outlet) {
           return outlet.activatedRouteData.state;
        }

Поэтому все, что мы возвращаемся отсюда, будет сопоставлено с маршрутизацией переменных назначения "source => destination". Так что, если я могу изменить переменную назначения.

2- Так что я подумал, что если я объявлю переменную для [@routeTransition] = "myVarible" и обновлю ее, она должна работать. Но она не сработала. Я не знаю почему.

3- Итак, я создал общий сервис для установки и получения названия анимации.

import { Injectable } from '@angular/core';
import {trigger, query, transition, style, animate, state, group} from '@angular/animations';

@Injectable()
export class AnimationControllerService {

  currentAnimation: any = null;
  currentAnimationId: number = -1;
  public animations: any;
  constructor() {

  }
  setCurrentAnimation(animationId) {
    var nextAnimation = "";
    var isDuplicate = false;

    switch(animationId) {
        case 1:
            nextAnimation = "slideToLeft";
            break;
        case 2:
            nextAnimation = "slideToRight";
            break;
        case 3:
            nextAnimation = "slideToTop";
            break;
        case 4:
            nextAnimation = "slideToBottom";
            break;
    }
    if(this.currentAnimation && (this.currentAnimation.indexOf("Duplicate") > -1)) {
        isDuplicate = true;
    }

    /* add duplicate if previous animation otherwise animation will not work */
    if((animationId == this.currentAnimationId) && !isDuplicate) {
        nextAnimation = nextAnimation + "Duplicate";
    }
    this.currentAnimation = nextAnimation;
    this.currentAnimationId = animationId;
  }
  getCurrentAnimation() {
    return this.currentAnimation;
  }
}

Как вы можете видеть, я задаю повторяющееся имя анимации, потому что моей предыдущей анимацией был slideLeft, и я снова хочу, чтобы slideLeft не работал, потому что "* => *" работает, если он получает другие параметры.

4- Теперь в app.component.html

<main [@routeTransition]="getAnimation()">
    <router-outlet></router-outlet>
</main>

5- Теперь app.component.ts выглядит так

import { AnimationControllerService } from './animationcontroller.service';
import { Component, Directive,HostBinding, HostListener, OnInit } from '@angular/core';
import 'rxjs/add/operator/filter';
import {trigger, query, transition, style, animate, state, group} from '@angular/animations';

const slideToRight = // animation code same as question
const slideToLeft = // animation code same as question

const slideToTop =// animation code same as question

const slideToBottom = // animation code same as question


@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css'],
    animations: [
        trigger('routeTransition', [
            transition("* => slideToLeft", slideToLeft),
            transition("* => slideToRight", slideToRight),
            transition("* => slideToTop", slideToTop),
            transition("* => slideToBottom", slideToBottom),
            transition("* => slideToLeftDuplicate", slideToLeft),
            transition("* => slideToRightDuplicate", slideToRight),
            transition("* => slideToTopDuplicate", slideToTop),
            transition("* => slideToBottomDuplicate", slideToBottom),
        ])
    ],
})

export class AppComponent {
    ios: boolean;
    iosClass: string = "";
    constructor(private animService: AnimationControllerService) {

    }
    getAnimation() {
        return this.animService.getCurrentAnimation();
    }
};

6 - Теперь вы можете легко перейти к любому маршруту, просто введя свой класс и установив текущую анимацию, а затем перейдя к своему маршруту. Так просто

this.animService.setCurrentAnimation(1);
this.router.navigate([navigateToPage]);

0 ответов

Другие вопросы по тегам