Angular 5 reusable animation with a single file

angular 5 animation demo angular 2 animations angular 5 slide animation angular 4 animations example angular 2 animation library @angular/platform-browser/animations angular 4 animation examples angular 4 animation demo

Angular animation document give some very good example to add the animation in component but it looks messy. What if we want to keep all the animation in separate file and use wherever we want. Keeping all animation in a separate file will be good idea because it will be easy to maintain and reuse the same animation as many times as we want. In this article we will create some basic animation and keep all the animation setting in one file and use on different pages:

First of all we need to import BrowserAnimationsModule in our app module and

import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
@NgModule({
  imports: [
    BrowserModule,  BrowserAnimationsModule,.....],
    declarations: [ AppComponent, HomeComponent,....],
    bootstrap: [ AppComponent ]
})

Let's add an animations.ts file to keep all the animation in one file and add our first animation to show the page coming from left

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

export const flyin = [
  trigger('flyin', [
      state('in', style({transform: 'translateX(0)'})),
      transition('void => *', [
        style({transform: 'translateX(-100%)'}),
        animate('700ms ease-in')            
      ])
    ]) 
];

Let's look into above code:

  • export const flyin: so it can be imported in different component in future
  • state "in": state will declare an animation state with its associated styles within the given trigger.
  • Some dependencies imported from @angular/animations
  • An exportable animation settings
  • transform: from -100% X position
  • Entire animation will take 700 milliseconds

How to use this animation file with pages? let's say we have a home component where we want to show the page to be rendered from left. In that case open the home component ts file and import our animation file created above, note, we don't need to import any animation related files.

import { flyin } from './animations';
@Component({
  selector: 'home-comp',
  templateUrl: './src/app/home.component.html',
  animations: [ flyin ]
})
export class HomeComponent { .... }
  • Imported flyin
  • in meta tags: animations: [ flyin ]

Now we need to use this flyin in our html to animate the page. If we want to animate a portion of page then we can put the code on that element. So add the following code in html:

<div  [@flyin] ='in'>
    ....
    ....
</div> 

See the demo by clicking on nav-bar menu or remove item from home page list by clicking on it.

We have another page about and we want this page to be rendered by rotating around 180 degree, let's add the animation for it in the same file just next to our previous code:

export const rotateIn = [
  trigger('rotateIn', [
      state('in', style({transform: 'translateX(0)'})),
      transition('void => *', [
        style({transform: 'rotate(-180deg)'}),
        animate('700ms ease-out')

      ])
    ]) 
];

Note the difference this time, in style we use style({transform: 'rotate(-180deg)'})

In the same way import the animation in our about component ts file

import { rotateIn } from './animations'
@Component({
  selector: 'about-comp',
  templateUrl: './src/app/about.component.html',
  animations: [rotateIn]
})

And use the [@rotateIn] ='rotateIn' in our html element

<div class='row' [@rotateIn] ='in'>
  ...
  ...
</div>

While you will play the demo, notice we are not rotating (animating) the page heading but only the content of the page.

Let's see another example to show the page from the bottom, say the contact component, so add the animation for it in the same file where we added other animations.

export const flyFromBottom = [
  trigger('flyFromBottom', [
      state('in', style({transform: 'translateY(0)'})),
      transition('void => *', [
        style({transform: 'translateY(100%)'}),
        animate('700ms ease-in')            
      ])
    ]) 
];

Except the animation style nothing is new, just we change the translateX to translateY. Rest of settings are same like the time of animation, if you want you can change the test. Let import and this animation into our page

import { flyFromBottom } from './animations';
@Component({
  selector: 'about-comp',
  templateUrl: './src/app/contact.component.html',
  animations: [ flyFromBottom ]
})
// in html
<div  [@flyin] ='in'>...</div>

All these were to animate only when page load what about the list item when adding ore removing, let's create one for that

export const flyItems = [
  trigger('flyItems', [
    state('in', style({transform: 'translateX(0)'})),
    transition('void => *', [
      animate(700, keyframes([
        style({opacity: 0, transform: 'translateX(-100%)', offset: 0}),
        style({opacity: 1, transform: 'translateX(0)',     offset: 1.0})
      ]))
    ]),
    transition('* => void', [
      animate(500, keyframes([
        style({opacity: 1, transform: 'translateX(0)',     offset: 0}),
        style({opacity: 0, transform: 'translateX(100%)',  offset: 1.0})
      ]))
    ])
  ])
];  
  • The void state is useful for defining enter and leave animations.
  • For example the * => void transition applies when the element leaves the view, regardless of what state it was in before it left.

Using the void and * states you can define transitions that animate the entering and leaving of elements:

  • Enter: void => *
  • Leave: * => void

Rest are simple style settings

Let's add this animation on home page to show the list with our previous animations:

import { flyin, flyItems } from './animations'
@Component({
  selector: 'home-comp',
  templateUrl: './src/app/home.component.html',
  animations: [ flyin, flyItems]
})

And home page html will looks like this:

<div  [@flyin] ='in'>
  <h4>Home </h4>
  <hr />
  <p>Click an item to remove</p>
  <ul class='items'>
    <li *ngFor="let item of items"  class='pointer'
        [@flyItems] ='in' (click)='remove(item)'
       >{{item}}</li>
  </ul>

  <div class='row'>
    <div class='col-6'>
      <input type='text' [(ngModel)]='item'
         namee='item' class='form-control form-control-sm' />
    </div>
    <div class='col-6'>
      <button type='button' class='btn btn-sm btn-info' (click)='add()'>Add</button>
    </div>
  </div>
</div>

items is an array in our component to hold the list of items

Here is the complete code for our home page component:

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

import { flyin, flyItems } from './animations'

@Component({
  selector: 'home-comp',
  templateUrl: './src/app/home.component.html',
  animations: [ flyin, flyItems]
})
export class HomeComponent implements OnInit{ 

   items: Array<string> = [];
   item:string;

   constructor() { }

   ngOnInit(){
     this.items.push('New Item 1');
     this.items.push('New Item 2');
     this.items.push('New Item 3');
   }

   add(){

     if(this.item != null)
      this.items.push(this.item);
      this.item = '';
   }
   remove(text){
     if(text != null){
       var index = this.items.indexOf(text);
       if (index > -1) {
            this.items.splice(index, 1);
       }
     }
   }
}   

And finally our animations.ts file will have 4 types of animation which can be used with any number of pages just by adding one line of import code.

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

export const flyin = [
  trigger('flyin', [
      state('in', style({transform: 'translateX(0)'})),
      transition('void => *', [
        style({transform: 'translateX(-100%)'}),
        animate('700ms ease-in')        
      ])
    ]) 
];

export const rotateIn = [
  trigger('rotateIn', [
      state('in', style({transform: 'translateX(0)'})),
      transition('void => *', [
        style({transform: 'rotate(-180deg)'}),
        animate('700ms ease-out')        
      ])
    ]) 
];

export const flyFromBottom = [
  trigger('flyFromBottom', [
      state('in', style({transform: 'translateY(0)'})),
      transition('void => *', [
        style({transform: 'translateY(100%)'}),
        animate('700ms ease-in')        
      ])
    ]) 
];

export const flyItems = [
  trigger('flyItems', [
    state('in', style({transform: 'translateX(0)'})),
    transition('void => *', [
      animate(700, keyframes([
        style({opacity: 0, transform: 'translateX(-100%)', offset: 0}),
        style({opacity: 1, transform: 'translateX(0)',     offset: 1.0})
      ]))
    ]),
    transition('* => void', [
      animate(500, keyframes([
        style({opacity: 1, transform: 'translateX(0)',     offset: 0}),
        style({opacity: 0, transform: 'translateX(100%)',  offset: 1.0})
      ]))
    ])
  ])
];
Ali Adravi Having 13+ years of experience in Microsoft Technologies (C#, ASP.Net, MVC and SQL Server). Worked with Metaoption LLC, for more than 9 years and still with the same company. Always ready to learn new technologies and tricks.
  • angular
  • animation
By Ali Adravi On 27 Mar, 18  Viewed: 1,594

Other blogs you may like

Angularjs powerful paging on table and searching with delay and demo

Paging on table is the basic requirement and most of us look for some grid so it can provide the complete feature of paging and sorting but in Angularjs it is so easy that anyone can achieve it by writing some code. I checked and found most of the available code give the paging feature in for 1 to... By Ali Adravi   On 14 Aug 2015  Viewed: 13,628

Angularjs Cascading Dropdown/Select with demo

Cascading dropdown with angularjs is easier than MVC and ASP.Net. In Angularjs ng-change is the best event to hook the function to get the second dropdown list items. In this article, we will try to fill the state dropdown on selection change of country and then fill the city dropdown on change... By Ali Adravi   On 06 Aug 2015  Viewed: 48,429

Angularjs CRUD with Web API, Entity Framework & Bootstrap modal popup part 2

Add/Edid Customer in Modal Popup --- In previous article we discussed how to search, delete and show detail of customer and contact list. In this article we will try to open the modal popup to add new customer and edit an existing customer record. I divided article in two parts because of the... By Ali Adravi   On 29 Jul 2015  Viewed: 17,427

Custom Directives in AngularJS with example and demo

Angularjs custom directives are the common to avoid the duplicate code, it is easy powerful and really nice. There are already too many directive have been created by experts but as a developer we need to write our own to achieve our specific goal. ng-model, ng-if, ng-show, ng-repeat all these are... By Ali Adravi   On 29 Jul 2015  Viewed: 3,886

Angularjs CRUD with Web API, Entity Framework & Bootstrap modal popup part 1

Search sort Insert update and delete are the basic features we need to learn first to learn any language, In this article we will try to create these features with Web API, bootstrap modal popup and ui.router. We will use enetity framework code first to save and retrieve data from database. We... By Ali Adravi   On 28 Jul 2015  Viewed: 28,855