Menu

Animando items con Ionic, en 5 pasos

animationsdemos - May 23, 2017 por Nicolas Molina
ionic3.3.0ionic-native3.10.3ionic-app-scripts1.3.7cordova-cli7.0.1ionic-cli3.3.0

Angular integra Web Animations API para ejecutar animaciones en css que aprovechan la GPU del dispositivo y se puedan controlar con JS, sin duda esto provee un mayor control en las animaciones que podemos hacer.

Actualización (21/05/2017)


Hemos actualizado este demo con el último release de Ionic 3, si aún estas en alguna de las versiones anteriores puedes seguir estos pasos de Ionic 2 a Ionic 3.

Ademas en este demo usamos la función de lazy loading y @IonicPage. Puedes ver el repositorio Demo108


Para hacer animaciones en Angular/Ionic tenemos varias funciones que son de gran utilidad para controlar y crear las animaciones:

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

Antes de empezar, es necesario entender los conceptos básicos para desarrollar el demo de este artículo.

State

Un state lo usamos para definir el estado de la animación, podemos tener muchos estados dentro de una animación, los estados se aplicarán al elemento del DOM donde se aplican estilos según cada estado:

state('inactive', style({
  backgroundColor: '#eee',
  transform: 'scale(1)'
})),
state('active',   style({
  backgroundColor: '#cfd8dc',
  transform: 'scale(1.1)'
})),

Transition

Con Transition podemos definir las reglas de animación al cambiar de un estado a otro:

transition('inactive => active', animate('100ms ease-in')),
transition('active => inactive', animate('100ms ease-out'))

En las transitions también podemos agregar estilos que solo se aplican durante la animación y que no harán parte de state.

En Angular tenemos dos estados muy útiles, uno es el comodín (The wildcard state) *, este se refiere a cualquier estado y es muy útil cuando no hay un estado definido.

Y el segundo estado es void que es llamado automáticamente cuando es ejecutada cualquier animación y será muy util para ejecutar las animaciones cuando un item es agregado o un ítem es eliminado.

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

Trigger:

Este será el evento con el cual vamos a ejecutar las animaciones de acuerdo a cada estado.

animations: [
  trigger('itemState', [
    state('inactive', style({
      backgroundColor: '#eee',
      transform: 'scale(1)'
    })),
    state('active',   style({
      backgroundColor: '#cfd8dc',
      transform: 'scale(1.1)'
    })),
    transition('inactive => active', animate('100ms ease-in')),
    transition('active => inactive', animate('100ms ease-out'))
  ])
]

Y para agregar la animación a un elemento del DOM, se agrega el trigger así:

<button ion-button (click)="item.state = 'active'">Active</button>
<button ion-button (click)="item.state = 'inactive'">InActive</button>
<ion-item [@itemState]="item.state">...</ion-item>

Con estas bases y conceptos ahora podremos hacer un demo sencillo donde haremos una animación cuando un ítem es agregado y otra animación cuando es eliminado. La documentación oficial sobre animaciones la pueden ver aqui.

Paso 1: Iniciando el proyecto

Lo primero que haremos será iniciar un nuevo proyecto con ionic, vamos a nuestra terminal y ejecutamos:

ionic start demo108 blank

Ionic crea una carpeta con el nombre del proyecto, nuestro siguiente paso será ubicarnos dentro a la carpeta del proyecto desde nuestra terminal con:

cd demo108

El proyecto inicia con el template blank y por esto tendremos una estructura básica del proyecto, la carpeta en la que vamos a trabajar será src:

Paso 2: Agregar BrowserAnimationsModule

Ahora debemos instalar el módulo @angular/animations, así:

npm install @angular/animations --save

Luego debemos importar BrowserAnimationsModule en el archivo app.module.ts, asi:

import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

...

@NgModule({
  declarations: [
    MyApp
  ],
  imports: [
    BrowserModule,
    HttpModule,
    BrowserAnimationsModule,
    IonicModule.forRoot(MyApp),
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    DuetyApp
  ],
  providers: [...]
})
export class AppModule {}

Paso 2.1 (Solo para IOS): Agregar polyfill.

IOS no soporta aún Web Animations API, por esto debemos agregaremos un polyfill que agrega soporte para IOS, descargamos el archivo web-animations.min.js desde https://rawgit.com/web-animations/web-animations-js/master/web-animations.min.js y lo incluimos en src/index.html, así:

<body>
  ...
  <script src="build/polyfills.js"></script>
  <script src="assets/js/web-animations.min.js"></script>
  ...
</body>

Paso 3: Creando la animación

Vamos a crear un trigger llamado itemState que tendrá el estado in, este estado representa al item cuando sea agregado a la lista. Luego definimos las animación de entrada con 'void => *' a la cual le agregamos un estilo por defecto antes que ejecute la animación, luego en la animación de salida con * => void y agregamos un estilo a esta.

animations: [
  trigger('itemState', [
    state('in', style({opacity: 1, transform: 'translateX(0)'})),
    transition('void => *', [
      style({
        opacity: 0,
        transform: 'translateX(-100%)'
      }),
      animate('300ms ease-in')
    ]),
    transition('* => void', animate('300ms ease-out', style({
      opacity: 0,
      transform: 'translateX(100%)'
    }))),
  ])
]

Con lo cual lograremos el siguiente efecto:

HomePage finalmente quedará asi:

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

import { IonicPage, NavController } from 'ionic-angular';

@IonicPage()
@Component({
  selector: 'page-home',
  templateUrl: 'home.html',
  animations: [
    trigger('itemState', [
      state('in', style({opacity: 1, transform: 'translateX(0)'})),
      //Enter
      transition('void => *', [
        style({
          opacity: 0,
          transform: 'translateX(-100%)'
        }),
        animate('300ms ease-in')
      ]),
      //Leave
      transition('* => void', animate('300ms ease-out', style({
        opacity: 0,
        transform: 'translateX(100%)'
      }))),
    ])
  ]
})
export class HomePage {
  ...
}

Paso 4: Agregando y eliminando items.

Ahora vamos a agregar el metodo add qué agregará un item a la lista y remove que elimina un item de la lista, así:

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

import { IonicPage, NavController } from 'ionic-angular';

@IonicPage()
@Component({
  selector: 'page-home',
  templateUrl: 'home.html',
  animations: [...]
})
export class HomePage {

  items: any[] = [];

  constructor(public navCtrl: NavController) {}

  add(){
    this.items.push({
      title: 'item',
      state: 'in'
    });
  }

  remove(){
    this.items.splice(0,1);
  }

}

Paso 5: El template.

En el template crearemos dos botones, un botón para agregar un item y el segundo botón para eliminar un item . Luego itereamos la lista y agregamos el trigger de animacion que depende del estado del item.


<ion-header>
  <ion-navbar color="primary">
    <ion-title>
      Demo 108
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
  <button ion-button (click)="add()">Add Item</button>
  <button ion-button (click)="remove()">Remove Item</button>
  <ion-list>
    <ion-list-header>
      Items
    </ion-list-header>
    <ion-item [@itemState]="item.state" *ngFor="let item of items">
      {{ item.title }}
    </ion-item>
  </ion-list>
</ion-content>

En proximos demos trabajaremos en animaciones más complejas =).

Ver código

Recuerda:

Si quieres ejecutar este demo en tu computadora, debes tener el entorno de ionic instalado y luego de descargar o clonar el proyecto debes ubicarte en tu proyecto en la terminal y luego ejecutar

npm install

Y luego

ionic cordova prepare

esto es para descargar todas las dependencias del proyecto.

¡Compártelo!