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:
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:
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"></div>
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:
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.