Angular 路由器过渡动画有条件地左右滑动

Angular router transition animations slide both left and right conditionally

我已阅读这篇关于 Angular 的路由器转换动画的文章:

https://medium.com/google-developer-experts/angular-supercharge-your-router-transitions-using-new-animation-features-v4-3-3eb341ede6c8

并且:

但是,这太静态了。我希望它根据选项卡的顺序向左滑动 和向右滑动

是否可以为此创建路由器动画?我的意思示例如下:

https://material.angular.io/components/tabs/examples

看看它如何非常自然地向左 滑动 和向右 滑动,具体取决于您在哪个选项卡上。

这必须是动态的,因为选项卡将在运行时添加。

我已经设法让它在 "faking" 它所处的状态下工作。

component.html:

<div [@animRoutes]="pageState">
   <router-outlet></router-outlet>
</div>

pageStatecomponent.ts 文件中的一个 变量

每当我点击一个我想右移的选项卡时,我会将 pageState 设置为 rightleft 也是如此,并让 Angular 剩下的接手

注意: 您必须创建 rightright1 状态作为 hack,因为 Angular 目前不支持 right => right 状态转换!! left当然也是如此。

我的@Component注释如下:

@Component({
    selector: 'app-workspace-container',
    templateUrl: './workspace-container.component.html',
    styleUrls: ['./workspace-container.component.scss'],
    animations: [
        trigger('animRoutes', [
            transition('* => right', right),
            transition('* => left', left),
            transition('* => right1', right),
            transition('* => left1', left),
        ]),
    ],
    changeDetection: ChangeDetectionStrategy.OnPush,
})

其中leftleft1rightright1是:

const left = [
    query(':enter, :leave', style({ position: 'fixed', width: '100%' }), { optional: true }),
    group([
        query(':enter', [style({ transform: 'translateX(-100%)' }), animate('.3s ease-out', style({ transform: 'translateX(0%)' }))], {
            optional: true,
        }),
        query(':leave', [style({ transform: 'translateX(0%)' }), animate('.3s ease-out', style({ transform: 'translateX(100%)' }))], {
            optional: true,
        }),
    ]),
];

const right = [
    query(':enter, :leave', style({ position: 'fixed', width: '100%' }), { optional: true }),
    group([
        query(':enter', [style({ transform: 'translateX(100%)' }), animate('.3s ease-out', style({ transform: 'translateX(0%)' }))], {
            optional: true,
        }),
        query(':leave', [style({ transform: 'translateX(0%)' }), animate('.3s ease-out', style({ transform: 'translateX(-100%)' }))], {
            optional: true,
        }),
    ]),
];

TL;DR: 将您要进入的状态设为 变量 ,这样您就可以动态设置您希望的状态你会。

今天事情有点简单,因为新的动画别名存在 :increment:decrement。别名已在 Angular 5.

中引入

所以我修改后的方案是:

    @Component({
      selector: 'app-workspace-container',
      templateUrl: './workspace-container.component.html',
      styleUrls: ['./workspace-container.component.scss'],
      animations: [
        trigger('animRoutes', [
          transition(':increment', right),
          transition(':decrement', left),
        ]),
      ],
  })
  export class ComponentContainingRouterOutlet implements OnDestroy, OnInit {
    //... ngOnInit,ngOnDestroy

    constructor( private route: ActivatedRoute ) { }

    animationState: number;

    onActivate($event) {
      this.animationState = this.route.firstChild.snapshot.data['routeIdx'];
    }
  }

router-outlet 位置调用动画:

<div [@animRoutes]="animationState">
  <router-outlet (activate)="onActivate($event)"></router-outlet>
</div>

修改路由定义为例,看data: { routeIdx: X } :

    const routes: Routes = [
      {
        path: 'routeOne',
        component: ComponentOne,
        data: { routeIdx: 0 }
      },
      {
        path: 'routeTwo',
        component: ComponentTwo,
        data: { routeIdx: 1}
      },
      {
        path: 'routeThree',
        component: ComponentThree,
        data: { routeIdx: 2 }
      },
      {
        path: 'routeFour',
        component: ComponentFour,
        data: { routeIdx: 3 }
      },
      {
        path: '',
        redirectTo: 'routeOne',
        pathMatch: 'full'
      }
    ]

转换与 中的相同 post:

const left = [
    query(':enter, :leave', style({ position: 'fixed', width: '100%' }), { optional: true }),
    group([
        query(':enter', [style({ transform: 'translateX(-100%)' }), animate('.3s ease-out', style({ transform: 'translateX(0%)' }))], {
            optional: true,
        }),
        query(':leave', [style({ transform: 'translateX(0%)' }), animate('.3s ease-out', style({ transform: 'translateX(100%)' }))], {
            optional: true,
        }),
    ]),
];

const right = [
    query(':enter, :leave', style({ position: 'fixed', width: '100%' }), { optional: true }),
    group([
        query(':enter', [style({ transform: 'translateX(100%)' }), animate('.3s ease-out', style({ transform: 'translateX(0%)' }))], {
            optional: true,
        }),
        query(':leave', [style({ transform: 'translateX(0%)' }), animate('.3s ease-out', style({ transform: 'translateX(-100%)' }))], {
            optional: true,
        }),
    ]),
];

Michal.S 的出色解决方案。所以我也可以在没有 Routechange 的情况下使用它,但也可以在你自己的选项卡组件上使用它。

如果您有自定义选项卡控件,您可以这样做:

第一步:添加上面的动画

const left = [
  query(':enter, :leave', style({ position: 'absolute', width: '100%' }), { optional: true }), // or fixed
  group([
    query(':enter', [style({ transform: 'translateX(-100%)' }), animate('.4s ease-out', style({ transform: 'translateX(0%)' }))], {
      optional: true,
    }),
    query(':leave', [style({ transform: 'translateX(0%)' }), animate('.4s ease-out', style({ transform: 'translateX(100%)' }))], {
      optional: true,
    }),
  ]),
];

const right = [
  query(':enter, :leave', style({ position: 'absolute', width: '100%' }), { optional: true }),
  group([
    query(':enter', [style({ transform: 'translateX(100%)' }), animate('.4s ease-out', style({ transform: 'translateX(0%)' }))], {
      optional: true,
    }),
    query(':leave', [style({ transform: 'translateX(0%)' }), animate('.4s ease-out', style({ transform: 'translateX(-100%)' }))], {
      optional: true,
    }),
  ]),
];

第2步:在模板中将触发器添加到动画项的容器中。相对或弹性定位。

<div [@animStep]="currentStep">
    <app-step1 *ngIf=“currentStep === 1”></app-step1>
    <app-step2 *ngIf=“currentStep === 2”></app-step2>
    <app-step3 *ngIf=“currentStep === 3”></app-step3>
</div>

第 3 步:在组件装饰器中添加动画

// component
animations: [
  trigger('animStep', [
    transition(':increment', right),
    transition(':decrement', left),
  ]),
],

第 3 步:触发值的变化

currentStep += 1;