Angular router transition animations slide both left and right conditionally

Dolan picture Dolan · Feb 22, 2018 · Viewed 8.1k times · Source

I have read this article about Router transition Animations for Angular:

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

And:

Angular 2 "slide in animation" of a routed component

However, this is too static. I want it to slide left and right depending on the order of the tab.

Is it possible to create router animations for this? Example of what I mean is below:

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

Look how it slides BOTH left and right very naturally depending on what tab you are on.

This has to be dynamic, because the tabs will be added at runtime.

Answer

Michal.S picture Michal.S · Jul 20, 2018

Today things are a bit simpler because new animation aliases exist as :increment and :decrement. Aliases have been introduced in Angular 5.

So my modified solution is:

    @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'];
    }
  }

Call animation at router-outlet position:

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

modify routes definition as example, look at 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'
      }
    ]

And transitions are the same as in Dolan's 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,
        }),
    ]),
];