Animaciones
Opciones tecnológicas
Las animaciones se utilizan a menudo para dar vida a las aplicaciones. Hoy en día, los navegadores tienen un buen soporte para las animaciones CSS, y existen varias bibliotecas que proporcionan animaciones rápidas basadas en JavaScript. También hay una API web emergente y un polyfill si prefieres usar las últimas novedades.
Mithril.js no proporciona una API de animación propia, ya que estas otras opciones son más que suficientes para lograr animaciones ricas y complejas. Sin embargo, Mithril.js ofrece hooks para facilitar el desarrollo en casos específicos donde tradicionalmente es difícil implementar animaciones.
Animación en la creación de elementos
Animar un elemento con CSS al crearlo es muy sencillo. Simplemente añade una animación a una clase CSS:
.fancy {
animation: fade-in 0.5s;
}
@keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}var FancyComponent = {
view: function () {
return m('.fancy', 'Hola mundo');
},
};
m.mount(document.body, FancyComponent);Animación en la eliminación de elementos
El desafío de animar antes de eliminar un elemento radica en que debemos esperar a que la animación se complete antes de poder eliminarlo realmente. Afortunadamente, Mithril.js ofrece el hook onbeforeremove que nos permite diferir la eliminación de un elemento.
Creemos una animación que desvanezca la opacidad de 1 a 0.
.exit {
animation: fade-out 0.5s;
}
@keyframes fade-out {
from {
opacity: 1;
}
to {
opacity: 0;
}
}Ahora creemos un componente que muestre y oculte el FancyComponent que creamos en la sección anterior:
var on = true;
var Toggler = {
view: function () {
return [
m(
'button',
{
onclick: function () {
on = !on;
},
},
'Alternar'
),
on ? m(FancyComponent) : null,
];
},
};A continuación, modifiquemos FancyComponent para que se desvanezca cuando se elimine:
var FancyComponent = {
onbeforeremove: function (vnode) {
vnode.dom.classList.add('exit');
return new Promise(function (resolve) {
vnode.dom.addEventListener('animationend', resolve);
});
},
view: function () {
return m('.fancy', 'Hola mundo');
},
};vnode.dom apunta al elemento DOM raíz del componente (<div class="fancy">). Utilizamos la API classList aquí para añadir la clase exit a <div class="fancy">.
Luego devolvemos una Promesa que se resuelve cuando se dispara el evento animationend. Cuando devolvemos una promesa desde onbeforeremove, Mithril.js espera hasta que la promesa se resuelva y solo entonces elimina el elemento. En este caso, espera a que termine la animación de salida.
Podemos verificar que tanto las animaciones de entrada como de salida funcionan montando el componente Toggler:
m.mount(document.body, Toggler);Ten en cuenta que el hook onbeforeremove solo se dispara en el elemento que pierde su parentNode cuando un elemento se elimina del DOM. Este comportamiento es intencional y existe para evitar una experiencia de usuario potencialmente incómoda donde cada animación de salida concebible en la página se ejecutaría en un cambio de ruta. Si tu animación de salida no se está ejecutando, asegúrate de adjuntar el handler onbeforeremove lo más arriba posible en la jerarquía que tenga sentido para asegurar que se llame a tu código de animación.
Rendimiento
Al crear animaciones, se recomienda que solo utilices las reglas CSS opacity y transform, ya que estas pueden ser aceleradas por hardware por los navegadores modernos y ofrecen un mejor rendimiento que animar top, left, width y height.
También se recomienda que evites la regla box-shadow y los selectores como :nth-child, ya que también son opciones que requieren muchos recursos. Si quieres animar un box-shadow, considera poner la regla box-shadow en un pseudoelemento, y animar la opacidad de ese elemento en su lugar. Otras cosas que pueden ser costosas son las imágenes grandes o escaladas dinámicamente y los elementos superpuestos con diferentes valores de position (por ejemplo, un elemento posicionado absolutamente sobre un elemento fijo).