Ionic 2 Animated Login Screen

Create an Animated Login Screen in Ionic 2



·

In a recent tutorial, I covered how to use the Web Animations API in Ionic 2 with Angular 2 animations. If you’re unfamiliar with either the Web Animations API or how to use animations in Angular 2, I would recommend reading that tutorial first.

While the last tutorial focused on covering the basics of how the animations work, and some simple examples, this tutorial will walk you through creating something with more real world value. We will be building a custom login screen with some animations, which will end up looking like this:

Ionic 2 Login Animation

This tutorial is going to focus purely on building out the animations, not the layout or CSS, if you would like more information on those topics, I would recommend the following tutorials:

Before We Get Started

Before you go through this tutorial, you should have at least a basic understanding of Ionic 2 concepts. You must also already have Ionic 2 set up on your machine.

If you’re not familiar with Ionic 2 already, I’d recommend reading my Ionic 2 Beginners Guide first to get up and running and understand the basic concepts. If you want a much more detailed guide for learning Ionic 2, then take a look at Building Mobile Apps with Ionic 2.

1. Generate a New Ionic 2 Application

Let’s start by generating a new Ionic 2 application. We will be using the blank template, and we will be adding one extra page to act as the login page that we will be designing.

Run the following command to generate a new Ionic 2 application

ionic start ionic2-login-animation blank --v2

Run the following command to generate the login page

ionic g page LoginPage

Since we’ve generated a new page, we are going to have to make sure we set it up in the app.module.ts file.

Modify src/app/app.module.ts to reflect the following:

import { NgModule } from '@angular/core';
import { IonicApp, IonicModule } from 'ionic-angular';
import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
import { LoginPage } from '../pages/login-page/login-page';

@NgModule({
  declarations: [
    MyApp,
    HomePage,
    LoginPage
  ],
  imports: [
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage,
    LoginPage
  ],
  providers: []
})
export class AppModule {}

We’re just about ready to go, but since we will be working with the Login page (not the Home page) we are going to change the root page to be the login page as well.

Modify src/app/app.component.ts to reflect the following:

import { Component } from '@angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar } from 'ionic-native';
import { LoginPage } from '../pages/login-page/login-page';

@Component({
  template: `<ion-nav [root]="rootPage"></ion-nav>`
})
export class MyApp {
  rootPage = LoginPage;

  constructor(platform: Platform) {
    platform.ready().then(() => {
      StatusBar.styleDefault();
    });
  }
}

2. Include the Polyfill

If you read the previous tutorial, you would know that the Web Animations API that Angular 2 uses for animations is not supported in all browsers, one of those being iOS Safari which is certainly a problem if you want to deploy your app to iOS.

Fortunately, there is a polyfill available here that you can use to get animations working on iOS.

Add web-animations.min.js and web-animations.min.js.map to a folder at src/assets/js/ in your project (you will have to create the js folder).

Add the following line to your index.html file:

<script src="web-animations.min.js"></script>

3. Set up the Images

If you take a look at the animation again:

<a href="https://www.joshmorony.com/wp-content/uploads/2016/08/login-animation.gif"><img src="https://www.joshmorony.com/wp-content/uploads/2016/08/login-animation.gif" alt="Ionic 2 Login Animation" width="480" height="846" class="aligncenter size-full wp-image-5909" /></a>

you will see that we are making use of two images: a transparent image with a background pattern of some clouds, and the logo. The background layer slides in first, followed shortly after by the logo.

You will need to add the images you wish to use inside of the *src/assets/images folder. If you would like to use the same images that I am using for the sake of the tutorial, you can download them by grabbing the source code for this tutorial (enter your email in the box near the top of this post).

4. Create the Layout

Now we're going to set up our layout as it will be after the animations have finished. We will be adding our two images, a form for logging in, and a login button.

Modify src/pages/login-page/login-page.html to reflect the following:

<ion-content>

  <div padding [@flyInBottomFast]="cloudState" id="cloud-layer">

    <ion-row>
      <ion-col>
        <img [@flyInBottomSlow]="logoState" src="assets/images/joshuamorony.png" />
      </ion-col>
    </ion-row>

    <ion-row>
      <ion-col>
        <ion-list inset [@bounceInBottom]="formState">

          <ion-item>
            <ion-label>Username</ion-label>
            <ion-input type="text"></ion-input>
          </ion-item>

          <ion-item>
            <ion-label>Password</ion-label>
            <ion-input type="password"></ion-input>
          </ion-item>

        </ion-list>
      </ion-col>
    </ion-row>

    <ion-row>
      <ion-col>
        <button ion-button class="login-button" [@fadeIn]="loginState">Login</button>
      </ion-col>
    </ion-row>

  </div>

</ion-content>

We’ve set up the basic structure of our login page here, we’re simply organising a few different components inside of a grid, and then everything is contained with a <div> that holds the background image.

Notice that we have also set up the animations for each of the elements that are going to be animated, e.g:

<div padding [@flyInBottomFast]="cloudState" id="cloud-layer">

If you don’t remember from the last tutorial, the @flyInBottomFast is the name of the trigger for the animation we will be using, and cloudState is the variable we will have in the class definition that controls the state of the animation.

Now we’ll just add a bit of styling to the login page.

Modify login.scss to reflect the following:

.ios, .md {

  page-login {

    .scroll-content {
      background-color: #42c7ff;
      display: flex;
      flex-direction: column;
      overflow: hidden;
    }

    img {
      width: 50%;
      height: auto;
      margin: 0 auto;
    }

    #cloud-layer {
      background-image: url(../assets/images/cloud-layer.png);
      background-size: cover;
      width: 100%;
      height: 100%;
    }

      ion-row {
        align-items: center;
        text-align: center;
      }

      ion-item {
          border-radius: 30px !important;
          padding-left: 10px !important;
          margin-bottom: 10px;
          background-color: #f6f6f6;
          opacity: 0.7;
          font-size: 0.9em;
      }

      ion-list {
          margin: 0;
      }

      .login-button {
          width: 100%;
          border-radius: 30px;
          font-size: 0.9em;
          border: 1px solid #fff;
          background-color: #39acdc;
      }

  }

}

5. Create the Animations

Now into the fun stuff. Since I’ve covered how to create animations in Angular 2 previously, I am not going to go into detail here, but we are going to cover some new things that the previous tutorial didn’t.

Let’s get all of our animations set up right away, and then talk through them.

Modify login.ts to reflect the following:

import { Component, trigger, state, style, transition, animate, keyframes } from '@angular/core';
import { NavController } from 'ionic-angular';

@Component({
  selector: 'page-login',
  templateUrl: 'login-page.html',

  animations: [

    //For the logo
    trigger('flyInBottomSlow', [
      state('in', style({
        transform: 'translate3d(0,0,0)'
      })),
      transition('void => *', [
        style({transform: 'translate3d(0,2000px,0'}),
        animate('2000ms ease-in-out')
      ])
    ]),

    //For the background detail
    trigger('flyInBottomFast', [
      state('in', style({
        transform: 'translate3d(0,0,0)'
      })),
      transition('void => *', [
        style({transform: 'translate3d(0,2000px,0)'}),
        animate('1000ms ease-in-out')
      ])
    ]),

    //For the login form
    trigger('bounceInBottom', [
      state('in', style({
        transform: 'translate3d(0,0,0)'
      })),
      transition('void => *', [
        animate('2000ms 200ms ease-in', keyframes([
          style({transform: 'translate3d(0,2000px,0)', offset: 0}),
          style({transform: 'translate3d(0,-20px,0)', offset: 0.9}),
          style({transform: 'translate3d(0,0,0)', offset: 1}) 
        ]))
      ])
    ]),

    //For login button
    trigger('fadeIn', [
      state('in', style({
        opacity: 1
      })),
      transition('void => *', [
        style({opacity: 0}),
        animate('1000ms 2000ms ease-in')
      ])
    ])
  ]
})
export class LoginPage {

  logoState: any = "in";
  cloudState: any = "in";
  loginState: any = "in";
  formState: any = "in";

  constructor(public navCtrl: NavController) {

  }

}

We’ve set up four animations here:

  • flyInBottomSlow
  • flyInBottomFast
  • bounceInBottom
  • fadeIn

The flyInBottomSlow animation will animate the element from outside of the bottom of the screen into its resting position. Notice that in the transition we have the state transition from void to * (any state). We never used void in the last tutorial, it is used to transition elements that have not yet been added to the screen. So by adding a void => * transition, the animation will take place as soon as the element is added to the screen.

Another difference here is that we usually define the style in a state, and then we can switch an element between different states to animate to that style. With this transition though, we define the style in the transition itself, rather than in its own state.

The flyInBottomFast animation is pretty much exactly the same, except the animation completes a little faster. With the bounceInBottom animation we use keyframes (which we covered in the last tutorial) to add various stages to the animation – it will first transition from the bottom of the page to a little bit past its final resting position, and then in the last 10% of the animation will settle back down into its normal position.

Finally, we have fadeIn which simply animates the opacity of the element from 0 to 1. Also notice that the last two animations have a delay inside of the animate function, so that they wait a little bit before executing. The fadeIn animation for example will wait for 2000ms before beginning, and then complete its animation in 1000ms.

With these animations defined, the app should now look like this when you load it:

Ionic 2 Login Animation

Summary

We’ve covered an important new concept here in using void. It is something you will use frequently as quite often you will want to trigger an animation right away, rather than manually triggering it by changing a state in the class. Aside from that, this tutorial doesn’t really provide any new information over the last tutorial, but it shows you a much more real world and practical use of animations in Ionic 2.

What to watch next...

  • Liam Bayly

    Josh – Still new at Ionic 2 and I have the tutorial working, excellent tutorial btw, however when I create a function in the login.ts and try to call it within the login button it is saying it does not exist, I wonder because of the animations is the functionality that you create within the login.ts need to be called differently now ?

    its just a function that sends someone to a new page, the function works because I have tested it on other pages, its located directly below and outside the constructor

    • Corey Cole

      I think I may be having a similar issue. Ionic serve works great, but when I try to ionic build for platform browser, I get an error saying “TypeError: dirMeta.animations.map is not a function” in the ngc build step. I’ve tracked down what that function is and it can be found here:
      https://github.com/angular/angular/blob/55dfa1b69db31034b3dee7603a432f1e6181e978/modules/%40angular/compiler/src/metadata_resolver.ts
      I haven’t found a solution yet.

      • in my case problem was because in Component declaration of the material design dropdown there was an animation filed set as filed.
        so i deleted import and set all animations in this component directly like {…, animations: […], … } not {…, animations, …}

  • Rolvar

    Hi Josh, I am facing some issues with the ionic-keyboard-plugin on one iOS device, when user or password input got focus, the screen scroll up and when they lost focus, then the screen doesn’t scroll down again, how can disable this scroll?.

    Regards,

  • Anton

    Hi Josh, Is it possible in Ionic 2 zoom on image (pinch) ?

  • Hi Josh
    Thanks for article, is it possible to add another article about how can we create animation like this site “http://ionicmaterial.com/demo/” , for example for lists or expanded headers .

  • hardik

    how to get web-animations.min.js and web-animations.min.js.map?

    • Charlie The Potato

      Change the branch to “Master” on GitHub before downloading and you should find them.

  • Hanzo

    Hi, I’m trying to implement some animations with this library.

    If I try this on ionic serve –lab the animations works fine on ios, android an windows platforms but If I try the app on Ionic View app (IOS 10.2.1) the animations not start.

    What would be wrong?(I used master version of library)

    Thanks

  • Dimitri Podoliev

    Hi Josh!
    Many thanks for the awesome tutorial!
    I ran into a small problem. So all works well when I serve it inside my browser. But when I emulate it to an iOS device or run it on on iPhone (via XCode) the animation doesn’t work.
    I’m working on a Mac.

    Any ideas where I might have gone wrong?

    Many thanks!
    Dimitri

  • Edwin Ilovares

    The backgound in Android does not appeart

  • fahmi saad

    it seems it doesnt working. nothing show on interface

  • Gregory Cushing

    I could not get this working. I got module ./login errors. I also just get a blank page.

  • surjithvijayan

    HI Josh,
    This one working in android very smooth and beautiful but in IOS , transitions are not working ? Is there any fix for this ?