Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Animate routes based on route paths in angular (v2+)

Instead of attaching an animation to every component that is being routed to such as in this StackOverflow answer, or as in the first part of the official documentation. An example:

In hero-detail.component.ts:

import { Component, OnInit } from '@angular/core';
import { fadeInOutAnimation } from "app/app-routing.animation";

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  animations: [
    fadeInOutAnimation(300)
  ]
})
export class HomeComponent{       

}

In app-routing.animation.ts:

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

export const fadeInOutAnimation = function (fadeInTimeMS) {
  return trigger('fadeInOut', [
    transition(':enter', [   // :enter is alias to 'void => *'
      style({ opacity: 0 }),
      animate(fadeInTimeMS, style({ opacity: 1 }))
    ]),
    transition(':leave', [   // :leave is alias to '* => void'
      animate(fadeInTimeMS, style({ opacity: 0 }))
    ])
  ])
}

I want to animate routes based on route paths:

Applying route animations to individual components works for a simple demo, but in a real life app, it is better to animate routes based on route paths.

as stated at the end of the 'Adding animations to the routed component' in the angular documentation. It doesn't expand on how to do this though.

like image 730
Tom Avatar asked Apr 07 '17 22:04

Tom


People also ask

What is @routertransition in Angular?

Enable routing transition animationlink The Angular router comes with high-level animation functions that let you animate the transitions between views when a route changes. To produce an animation sequence when switching between routes, you need to define nested animation sequences.

What would you use in angular 2 to define route?

We use the router-outlet directive, an Angular 2 Routing directive that displays the active route (like ng-view ).


1 Answers

Here's an animation where you can see the view sliding left to right when you're going forward and right to left when you're going backward without adding the animation to components separately.

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

const leftToRight: AnimationMetadata[] = [
    /* order */
    /* 1 */ query(':enter, :leave', style({position: 'fixed', width: '100%'})
        , {optional: true}),
    /* 2 */ group([  // block executes in parallel
        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}),
    ])
];
const rightToLeft: AnimationMetadata[] = [
    /* order */
    /* 1 */ query(':enter, :leave', style({position: 'fixed', width: '100%'})
        , {optional: true}),
    /* 2 */ group([  // block executes in parallel
        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 const routerTransition = trigger('routerTransition', [
    transition('first_page => second_page', leftToRight),
    transition('second_page => first_page ', rightToLeft),
    transition('second_page => third_page', leftToRight),
    transition('third_page => second_page', rightToLeft),
]);

And import it in your AppComponent and add a function to return the route state. Don't forget the styles I have applied.

import {routerTransition} from "./router.animations";

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styles: [`
        /deep/ router-outlet ~ * {
            position: absolute;
            width: 100%;
        }
    `],
    animations: [routerTransition]
})
export class AppComponent implements {
    getState(outlet) {
        return outlet.activatedRouteData.state;
    }

    onDeactivate() {
        // document.body.scrollTop = 0;
        // Alternatively, you can scroll to top by using this other call:
        window.scrollTo(0, 0);
    }
}

Apply it to main tag as a directive

<main [@routerTransition]="getState(o)">
    <router-outlet #o="outlet" (deactivate)="onDeactivate()"></router-outlet>
</main>
like image 150
Lasitha Avatar answered Oct 02 '22 15:10

Lasitha