header_lecciones_v5

Tutorial Angular Animation

por Sebastián Moreno, el 19 de junio de 2019

h_tutorial_angular

Crear animaciones para diversos elementos de un sitio web nunca había sido tan sencillo como lo es hoy en día. La semana pasada hablamos un poco sobre la animación, su importancia en la web y nos enfocamos en Angular Animations. Por ello, detallamos las bases para usar dicho módulo y encontramos varias ventajas sobre otras formas de animación en la web.

Ahora para llevar lo que hablamos a un campo más práctico, haremos un pequeño tutorial. A continuación, crearemos una animación en la cual, al darle clic a la opción ingresar o registrarse, se desplazará al centro su respectivo botón.

Inicialmente la opción se ve así:

boton_sin_animar

El resultado esperado con la animación, quedaría así:

boton_animado

Para este tutorial, usaremos como componente principal el app.component y le agregaremos otros dos componentes cada uno con un botón específico, desde app.component activaremos las animaciones correspondientes que se aplicarán en dichos botones.

Para comenzar, crearemos un nuevo proyecto en angular escribiendo lo siguiente en la consola de comandos de nuestra preferencia:
ng new animation-login

Una vez creado el proyecto, para poder usar Angular Animation debemos importar el módulo BrowserAnimationsModule. Para esto, usando cualquier editor de texto, abrimos el proyecto y nos ubicamos en el archivo app.module.ts y escribimos la siguiente definición:

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

Agregamos el módulo en imports de NgModule:

@NgModule({ imports: [BrowserAnimationsModule // otras importaciones]})

En la consola de comandos, nos ubicamos en la carpeta app:
cd animation-login/src/app

Creamos dos nuevos componentes:
ng g c login

ng g c register

Abrimos login.component.html y añadimos el siguiente código:

<input type="submit" value="Iniciar Sesión" class="button" [@changeState]="currentState">

Hemos creado un elemento input al cual le aplicamos el trigger changeState, de esta forma en dicho elemento será aplicada la animación.

Le añadimos estilos al elemento, en el archivo login.component.scss agregamos los siguientes estilos:

.button{
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    position: absolute;
    background-color: #108dc7;
    border: 1.5px solid transparent;
    border-radius: 5px;
    margin-left: auto;
    margin-right: auto;
    height: 45px;
    color: white;
    font-family: 'Merriweather', Georgia, serif;;
    box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 3px 10px 0 rgba(0, 0, 0, 0.19);
    display: block;
}

Hacemos lo mismo para el registro. En register.component.html el código del elemento queda de la siguiente manera:

<input type="submit" value="Registrarse" class="button" [@changeState]="currentState">

En register.component.scss el código del elemento queda de la siguiente manera:

.button{
    position: absolute;
    background-color:#ef8e38;
    border: 1.5px solid transparent;
    border-radius: 5px;
    margin-left: auto;
    margin-right: auto;
    height: 45px;
    color: white;
    font-family: 'Merriweather', Georgia, serif;
    box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 3px 10px 0 rgba(0, 0, 0, 0.19);
    display: block;    
}

Ya teniendo los componentes creados, ahora definimos en ellos la animación que queremos que tengan. Para eso, abrimos el archivo login.component.ts y agregamos la siguiente importación:

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

Luego en el decorador @Component() le agregamos la siguiente metadata:

animations: [
    trigger('changeState', [
    state ('stateLogin', style({transform: 'translateX(-50%)', opacity: 1})),
    state ('stateRegister', style({transform: 'translateX(150%)', opacity: 0, display: 'none'})),
    transition('stateRegister=>stateLogin', [animate('0.3s ease-in')]),
    transition('stateLogin=>stateRegister', [animate('0.3s ease-out')])
])
]

Hemos definido el trigger con el nombre de changeState, al igual definimos dos estados, stateLogin con un desplazamiento de -50%, más opacidad completa, y stateRegister que disminuye su opacidad a cero (0) y se desplaza hacia la derecha. Ambas transiciones durarán 0,3 segundos y tendrán su respectivo easing.

Las animaciones serán activadas desde appComponent por medio de una variable, entonces debemos usar una propiedad de binding denominada Input, para poder usarla en login.component.ts, la importamos de angular/core:
import { Input } from '@angular/core';

A su vez la agregamos y la nombramos currentState en la clase de LoginComponent de la siguiente forma:
@Input() currentState;

Repetimos en el componente Register (register.component.ts) los mismos pasos hechos en el componente Login, con la excepción de cambiar los datos de la metadata de su decorador. Para cambiarlos, en register.component.ts actualizamos la metadata animations de la siguiente forma:

animations: [
    trigger ('changeState', [
    state ('stateRegister', style({transform: 'translateX(-50%)', opacity: 1})),
    state ('stateLogin', style({transform: 'translateX(-250%)', opacity: 0,     display:'none'})),
    transition('stateLogin=>stateRegister', [animate('0.3s ease-in')]),
    transition('stateRegister=>stateLogin', [animate('0.3s ease-out')])
    ])
]

Agregamos también la propiedad Input en la clase RegisterComponent:

@Input() currentState;

Así, ya tenemos los dos inputs que van a ser animados, ahora para poder activarlos nos basaremos en cambios de estado, el cambio de estado lo generamos por medio de botones desde el appComponent. Abrimos app.component.ts y añadimos en la clase AppComponent el siguiente código:

toState = 'stateLogin';

login(){
   this.toState = 'stateLogin'
}

register(){
   this.toState = 'stateRegister'
}

La variable toState nos permite darle como valor inicial el estado el cual queremos que inicie la animación. Las funciones login() y register() cambiarán dicho valor según el estado determinado en cada función.

Luego, en el archivo app.component.html añadimos el siguiente código:

<section class="background">
  <section class="block">
    <div class="logText">
       <button (click)="login()">Ingresar</button>
       <button (click)="register()" class="reg">Registrarse</button>
    </div>
    <nav>
       <form class="showLogin">
         <label>
            <p>
            <input name="e-mail" placeholder="Correo Electrónico">
            </p>
         </label>
         <label>
            <p>
            <input type="password" name="password"
            placeholder="Contraseña">
            </p>
         </label>
       </form>
    </nav>
    <div class="line">
       <app-login [currentState]="toState"></app-login>
       <app-register [currentState]="toState"></app-register>
    </div>
    <br>
  </section>
</section>

Hemos definido dos botones <button> (Ingresar y Registrarse), los cuales al darles clic llaman dos funciones (login() y register(), respectivamente). Hemos agregado además un formulario para solicitar correo electrónico y contraseña.

Al llamar los dos componentes (app-login y app-register) les hemos añadido a cada uno la propiedad de Input denominada currentState con la variable toState, la cual enviará el estado según el botón al cual se le haya dado clic.

Añadimos estilos al componente, en el archivo app.component.css agregamos el siguiente código:

@import url(https://fonts.googleapis.com/css?family=Ubuntu:700);

.background{
   height: 100vh;
   width: 100%;
   background: linear-gradient(225deg, rgba(239,142,56,1) 0%, rgba(16,141,199,1) 100%);
   align-items: center;
   position: relative;
   .block{
       position: relative;
       top: 35%;
       padding: 10px;
       display: flex;
       flex-direction: column;
       justify-content: center;
       width: 60%;
       max-width: 600px;
       min-width: 280px;
       height: 50vh;
       background-color: #f1f1f1;
       margin: 0 auto;
       box-shadow:0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 3px 10px 0 rgba(0, 0, 0, 0.19);    
       .line{
           display: flex;
           justify-content: center;
       }
       .logText{
           display: flex;
           justify-content: center;
           button{
               font-family: "Ubuntu", sans-serif;
               -webkit-appearance: none;
               -moz-appearance: none;
               appearance: none;
               background: transparent;
               border: none;
               font-size: 20px;
               color: #303030;
               position: relative;
               text-transform: uppercase;
               text-decoration: none;
               padding-bottom: 8px;
               outline: none;
               &:before, &:after {
                   content: "";
                   position: absolute;
                   bottom: 3px;
                   left: 0;
                   right: 0;
                   height: 3px;
                   background-color: rgba(16,141,199,1);
               }
               &.reg{
                   &:before, &:after{
                       background-color: rgba(239,142,56,1);
                   }
               }
               &:before {
                   opacity: 0;
                   transform: translateY(-8px);
                   transition: transform 0s cubic-bezier(0.175, 0.885, 0.32, 1.275), opacity 0s;
               }
               &:after {
                   opacity: 0;
                   transform: translateY(4px);
                   transition: transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275), opacity 0.2s;
               }
               &:hover:before, &:hover:after, &:focus:before, &:focus:after {
                   opacity: 1;
                   transform: translateY(0);
               }
               &:hover:before, &:focus:before {
                   transition: transform 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275), opacity 0.2s;   
               }
               &:hover:after, &:focus:after {
                   transition: transform 0s 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275), opacity 0s 0.2s;
               }
           }
       }
   }
}

input{
    height: 45px;
    width: 65%;
    min-width: 40px;
    min-width: 250px;
    background-color: rgba(0, 0, 0, .02);
    border: 1.5px solid transparent;
    border-radius: 4px;
    margin-left: auto;
    margin-right: auto;
    font-family: 'Merriweather', Georgia, serif;
    display: block;
}

Finalmente, para ver el resultado de la aplicación web, en la consola de comandos redactamos: ng serve -o
Al abrirse en el navegador la aplicación en http://localhost:4200/, la animación debería quedar así:

boton_animado

Conclusión

Así, de una manera sencilla y versátil se pueden lograr distintas animaciones que vuelven la aplicación web más amigable, brindado una mejor experiencia al usuario.
Si quieres consultar el código de este proyecto, se encuentra disponible aquí.

Ahora que contamos con conocimientos básicos sobre Angular Animation, podemos profundizar más sobre el módulo en esta guía publicada en Year of Moo.

Descarga la guia para trabajar con ambientes IBM Websphere portal

Temas:Tecnologia e Innovación

Lecciones Pragma

Lecciones en Academia Pragma

Aquí encontrarás tutoriales técnicos para que apliques en temas de desarrollo de software, cloud, calidad en software y aplicaciones móviles. 

También puedes visitar nuestro Blog con contenido actual sobre Transformación Digital, Marketing, Conocimiento de Usuario y más. 

Blog

Suscríbete a la academia

Descarga la Guía para trabajar con ambientes IBM Websphere Portal