VueJS - Transición y animación

En este capítulo, discutiremos las funciones de transición y animación disponibles en VueJS.

Transición

VueJS proporciona varias formas de aplicar la transición a los elementos HTML cuando se agregan / actualizan en el DOM. VueJS tiene un componente de transición incorporado que debe envolverse alrededor del elemento, que necesita transición.

Sintaxis

<transition name = "nameoftransition">
   <div></div>
</transition>

Consideremos un ejemplo para comprender el funcionamiento de la transición.

Ejemplo

<html>
   <head>
      <title>VueJs Instance</title>
      <script type = "text/javascript" src = "js/vue.js"></script>
   </head>
   <body>
      <style>
         .fade-enter-active, .fade-leave-active {
            transition: opacity 2s
         }
         .fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
            opacity: 0
         }
      </style>
      <div id = "databinding">
         <button v-on:click = "show = !show">Click Me</button>
         <transition name = "fade">
            <p v-show = "show" v-bind:style = "styleobj">Animation Example</p>
         </transition>
      </div>
      <script type = "text/javascript">
         var vm = new Vue({
            el: '#databinding',
            data: {
               show:true,
               styleobj :{
                  fontSize:'30px',
                  color:'red'
               }
            },
            methods : {
            }
         });
      </script>
   </body>
</html>

Hay un botón llamado clickme creado mediante el cual podemos cambiar el valor de la variable show de verdadero a falso y viceversa. Hay unp tagque muestra el elemento de texto solo si la variable es verdadera. Hemos envuelto la etiqueta p con el elemento de transición como se muestra en el siguiente fragmento de código.

<transition name = "fade">
   <p v-show = "show" v-bind:style = "styleobj">Animation Example</p>
</transition>

El nombre de la transición es fade. VueJS proporciona algunas clases estándar para la transición y las clases tienen como prefijo el nombre de la transición.

A continuación se presentan algunas clases estándar para la transición:

  • v-enter- Esta clase se llama inicialmente antes de que se actualice / agregue el elemento. Es el estado inicial.

  • v-enter-active- Esta clase se utiliza para definir el retardo, la duración y la curva de relajación para entrar en la fase de transición. Este es el estado activo para toda la clase y está disponible durante toda la fase de entrada.

  • v-leave - Agregado cuando se activa la transición de salida, eliminado.

  • v-leave-active- Aplicado durante la fase de salida. Se elimina cuando finaliza la transición. Esta clase se utiliza para aplicar la curva de retardo, duración y relajación durante la fase de salida.

Cada una de las clases anteriores tendrá como prefijo el nombre de la transición. Hemos dado el nombre de la transición como fundido, por lo tanto, el nombre de las clases se convierte en.fade_enter, .fade_enter_active, .fade_leave, .fade_leave_active.

Están definidos en el siguiente código.

<style>
   .fade-enter-active, .fade-leave-active {
      transition: opacity 2s
   }
   .fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
      opacity: 0
   }
</style>

El .fade_enter_active y .fade_leave_active se definen juntos y aplica una transición al inicio y al final de la etapa. La propiedad de opacidad se cambia a 0 en 2 segundos.

La duración se define en .fade_enter_active y .fade_leave_active. La etapa final se define en .fade_enter, .fade_leave_to.

La visualización en el navegador es la siguiente.

Al hacer clic en el botón, el texto desaparecerá en dos segundos.

Después de dos segundos, el texto desaparecerá por completo.

Consideremos otro ejemplo, donde hay una imagen y se desplaza en el eje x cuando se hace clic en el botón.

Ejemplo

<html>
   <head>
      <title>VueJs Instance</title>
      <script type = "text/javascript" src = "js/vue.js"></script>
   </head>
   <body>
      <style>
         .shiftx-enter-active, .shiftx-leave-active {
            transition: all 2s ease-in-out;
         }
         .shiftx-enter, .shiftx-leave-to /* .fade-leave-active below version 2.1.8 */ {
            transform :  translateX(100px);
         }
      </style>
      <div id = "databinding">
         <button v-on:click = "show = !show">Click Me</button>
         <transition name = "shiftx">
            <p v-show = "show">
               <img src = "images/img.jpg" style = "width:100px;height:100px;" />
            </p>
         </transition>
      </div>
      <script type = "text/javascript">
         var vm = new Vue({
            el: '#databinding',
            data: {
               show:true
            },
            methods : {
            }
         });
      </script>
   </body>
</html>

El nombre de la transición es shiftx. Se usa una propiedad de transformación para desplazar la imagen en el eje x en 100 px usando el siguiente fragmento de código.

<style>
   .shiftx-enter-active, .shiftx-leave-active {
      transition: all 2s ease-in-out;
   }
   .shiftx-enter, .shiftx-leave-to /* .fade-leave-active below version 2.1.8 */ {
      transform :  translateX(100px);
   }
</style>

A continuación se muestra la salida.

Al hacer clic en el botón, la imagen se desplazará 100px hacia la derecha como se muestra en la siguiente captura de pantalla.

Animación

Las animaciones se aplican de la misma manera que se realiza la transición. La animación también tiene clases que deben declararse para que se produzca el efecto.

Consideremos un ejemplo para ver cómo funciona la animación.

Ejemplo

<html>
   <head>
      <title>VueJs Instance</title>
      <script type = "text/javascript" src = "js/vue.js"></script>
   </head>
   <body>
      <style>
         .shiftx-enter-active {
            animation: shift-in 2s;
         }
         .shiftx-leave-active {
            animation: shift-in 2s reverse;
         }
         @keyframes shift-in {
            0%   {transform:rotateX(0deg);}
            25%  {transform:rotateX(90deg);}
            50%  {transform:rotateX(120deg);}
            75%  {transform:rotateX(180deg);}
            100% {transform:rotateX(360deg);}
         }
      </style>
      <div id = "databinding">
         <button v-on:click = "show = !show">Click Me</button>
         <transition name = "shiftx">
            <p v-show = "show">
               <img src = "images/img.jpg" style = "width:100px;height:100px;" />
            </p>
         </transition>
      </div>
      <script type = "text/javascript">
         var vm = new Vue({
            el: '#databinding',
            data: {
               show:true
            },
            methods : {
            }
         });
      </script>
   </body>
</html>

Para aplicar la animación, existen clases iguales a las de transición. En el código anterior, tenemos una imagen encerrada en la etiqueta p como se muestra en el siguiente código.

<transition name = "shiftx">
   <p v-show = "show"><img src = "images/img.jpg" style = "width:100px;height:100px;" /></p>
</transition>

El nombre de la transición es shiftx. La clase aplicada es la siguiente:

<style>
   .shiftx-enter-active {
      animation: shift-in 2s;
   }
   .shiftx-leave-active {
      animation: shift-in 2s reverse;
   }
   @keyframes shift-in {
      0%   {transform:rotateX(0deg);}
      25%  {transform:rotateX(90deg);}
      50%  {transform:rotateX(120deg);}
      75%  {transform:rotateX(180deg);}
      100% {transform:rotateX(360deg);}
   }
</style>

La clase tiene el prefijo del nombre de transición, es decir, shiftx-enter-active y .shiftx-leave-active. La animación se define con los fotogramas clave de 0% a 100%. Hay una transformación definida en cada uno de los fotogramas clave, como se muestra en el siguiente fragmento de código.

@keyframes shift-in {
   0%   {transform:rotateX(0deg);}
   25%  {transform:rotateX(90deg);}
   50%  {transform:rotateX(120deg);}
   75%  {transform:rotateX(180deg);}
   100% {transform:rotateX(360deg);}
}

A continuación se muestra la salida.

Al hacer clic en el botón, gira de 0 a 360 grados y desaparece.

Clases de transición personalizadas

VueJS proporciona una lista de clases personalizadas, que se pueden agregar como atributos al elemento de transición.

  • enter-class
  • enter-active-class
  • leave-class
  • leave-active-class

Básicamente, las clases personalizadas entran en juego cuando queremos usar una biblioteca CSS externa como animate.css.

Ejemplo

<html>
   <head>
      <link href = "https://cdn.jsdelivr.net/npm/[email protected]" rel = "stylesheet" type = "text/css">
      <script type = "text/javascript" src = "js/vue.js"></script>
   </head>
   <body>
      <div id = "animate" style = "text-align:center">
         <button @click = "show = !show"><span style = "font-size:25px;">Animate</span></button>
         <transition
            name = "custom-classes-transition"
            enter-active-class = "animated swing"
            leave-active-class = "animated bounceIn">
            <p v-if = "show"><span style = "font-size:25px;">Example</span></p>
         </transition>
      </div>
      <script type = "text/javascript">
         var vm =  new Vue({
            el: '#animate',
            data: {
               show: true
            }
         });
      </script>
   </body>
</html>

Salida

Salida

Salida

Hay dos animaciones aplicadas en el código anterior. Un enter-active-class = "swing animado" y otro dejar-active-class = "animado bounceIn". Estamos haciendo uso de clases de animación personalizadas para que la animación se aplique desde la biblioteca de terceros.

Duración de la transición explícita

Podemos aplicar transición y animación en el elemento usando VueJS. Vue espera el evento transionend y animationend para detectar si la animación o la transición está lista.

A veces, la transición puede provocar retrasos. En tales casos, podemos aplicar la duración explícitamente de la siguiente manera.

<transition :duration = "1000"></transition>
<transition :duration = "{ enter: 500, leave: 800 }">...</transition>

Podemos usar la propiedad duration con a: en el elemento de transición como se muestra arriba. En caso de que sea necesario especificar la duración por separado para entrar y salir, se puede hacer como se muestra en el código anterior.

Ganchos de JavaScript

Las clases de transición se pueden llamar como métodos utilizando eventos de JavaScript. Consideremos un ejemplo para una mejor comprensión.

Ejemplo

<html>
   <head>
      <title>VueJs Instance</title>
      <script type = "text/javascript" src = "js/vue.js"></script>
   </head>
   <body>
      <script src = "https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>
      <div id = "example-4">
         <button @click = "show = !show">
            <span style = "font-size:25px;">Toggle</span>
         </button>
         <transition  v-on:before-enter = "beforeEnter"
            v-on:enter = "enter"
            v-on:leave = "leave"
            v-bind:css = "false">
            <p v-if = "show" style = "font-size:25px;">Animation Example with velocity</p>
         </transition>
      </div>
      <script type = "text/javascript">
         var vm = new Vue({
            el: '#example-4',
            data: {
               show: false
            },
            methods: {
               beforeEnter: function (el) {
                  el.style.opacity = 0
               },
               enter: function (el, done) {
                  Velocity(el, { opacity: 1, fontSize: '25px' }, { duration: 1000 })
                  Velocity(el, { fontSize: '10px' }, { complete: done })
               },
               leave: function (el, done) {
                  Velocity(el, { translateX: '15px', rotateZ: '50deg' }, { duration: 1500 })
                  Velocity(el, { rotateZ: '100deg' }, { loop: 2 })
                  Velocity(el, {
                     rotateZ: '45deg',
                     translateY: '30px',
                     translateX: '30px',
                     opacity: 0
                  }, { complete: done })
               }
            }
         });
      </script>
   </body>
</html>

Salida

En el ejemplo anterior, estamos realizando una animación usando métodos js en el elemento de transición.

Los métodos de transición se aplican de la siguiente manera:

<transition  v-on:before-enter = "beforeEnter"
   v-on:enter = "enter"
   v-on:leave = "leave"
   v-bind:css = "false">
   <p v-if = "show" style = "font-size:25px;">Animation Example with velocity</p>
</transition>

Hay un prefijo agregado v-ony el nombre del evento al que se llama al método. Los métodos se definen en la instancia de Vue de la siguiente manera:

methods: {
   beforeEnter: function (el) {
      el.style.opacity = 0
   },
   enter: function (el, done) {
      Velocity(el, { opacity: 1, fontSize: '25px' }, { duration: 1000 })
      Velocity(el, { fontSize: '10px' }, { complete: done })
   },
   leave: function (el, done) {
      Velocity(el, { translateX: '15px', rotateZ: '50deg' }, { duration: 1500 })
      Velocity(el, { rotateZ: '100deg' }, { loop: 2 })
      Velocity(el, {
         rotateZ: '45deg',
         translateY: '30px',
         translateX: '30px',
         opacity: 0
      }, { complete: done })
   }
}

La transición requerida se aplica en cada uno de estos métodos. Hay una animación de opacidad aplicada al hacer clic en el botón y también cuando la animación está lista. La biblioteca de terceros se utiliza para la animación.

Hay una propiedad agregada en la transición v-bind: css = "false", que se hace para que Vue entienda que es una transición de JavaScript.

Transición en el renderizado inicial

Para agregar animación al principio, necesitamos agregar la propiedad 'aparecer' al elemento de transición.

Veamos un ejemplo para entenderlo mejor.

Ejemplo

<html>
   <head>
      <link href = "https://cdn.jsdelivr.net/npm/[email protected]" rel = "stylesheet" type = "text/css">
      <script type = "text/javascript" src = "js/vue.js"></script>
   </head>
   <body>
      <div id = "animate" style = "text-align:center">
         <transition
            appear
            appear-class = "custom-appear-class"
            appear-active-class = "animated bounceIn">
            <h1>BounceIn - Animation Example</h1>
         </transition>
         <transition
            appear
            appear-class = "custom-appear-class"
            appear-active-class = "animated swing">
            <h1>Swing - Animation Example</h1>
         </transition>
         <transition
            appear
            appear-class = "custom-appear-class"
            appear-active-class = "animated rubberBand">
            <h1>RubberBand - Animation Example</h1>
         </transition>
      </div>
      <script type = "text/javascript">
         var vm =  new Vue({
            el: '#animate',
            data: {
               show: true
            }
         });
      </script>
   </body>
</html>

En el ejemplo anterior, hemos utilizado tres animaciones diferentes de la biblioteca animate.css. Hemos agregado aparecer al elemento de transición.

Tras la ejecución del código anterior, lo siguiente será el resultado en el navegador.

Animación de componentes

Podemos envolver la transición de los componentes usando el siguiente código. Hemos utilizado el componente dinámico aquí.

Ejemplo

<html>
   <head>
      <title>VueJs Instance</title>
      <script type = "text/javascript" src = "js/vue.js"></script>
      <link href = "https://cdn.jsdelivr.net/npm/[email protected]" rel = "stylesheet" type = "text/css">
   </head>
   <body>
      <div id = "databinding" style = "text-align:center;">
         <transition  appear
            appear-class = "custom-appear-class"
            appear-active-class = "animated wobble">
            <component v-bind:is = "view"></component>
         </transition>
      </div>
      <script type = "text/javascript">
         var vm = new Vue({
            el: '#databinding',
            data: {
               view: 'component1'
            },
            components: {
               'component1': {
                  template: '<div><span style = "font-
                  size:25;color:red;">Animation on Components</span></div>'
               }
            }
         });
      </script>
   </body>
</html>

Salida