Mediante CSS se pueden crear animaciones CSS muy complejas y potentes. Sin embargo, es posible que en casos donde buscamos cosas muy específicas, necesitemos la potencia de Javascript para poder realizar animaciones avanzadas, ahí es donde entra Web Animations, que no es más que una forma de crear animaciones CSS desde Javascript.
Para crear una animación utilizaremos el método .animate()
, que se ejecuta sobre un elemento del DOM. Tenemos varias formas de utilizarlo, vamos a verlo en la tabla siguiente y en un ejemplo sencillo para empezar.
El método .animate()
tiene varias modalidades, vamos a explicar primero la más sencilla:
Método | Descripción |
---|---|
.animate(keyframes, duration) |
Crea y aplica una animación CSS que dura duration segundos. |
.animate(keyframes, options) |
Crea y aplica una animación CSS, con las opciones indicadas en options . |
Una vez tenemos el elemento donde queremos aplicar la animación, ejecutamos el método animate()
el cual va a tener dos parámetros:
El primer parámetro: Un objeto keyframes
, que son los fotogramas clave de la animación, con los cambios CSS que se irán aplicando. Equivale a la regla @keyframes
de CSS.
El segundo parámetro: Un número duration
, con la duración en milisegundos de la animación. Más adelante, veremos que este segundo parámetro puede ser también un objeto de opciones, con el que definir cosas más complejas. Lo veremos más adelante.
El siguiente fragmento de código Javascript busca un elemento con clase .element
y le aplica una animación que mueve el elemento hacia la derecha, luego hacia abajo, luego hacia la izquierda y luego hacia arriba, al punto de partida. Siempre en cantidades de 200px
:
const element = document.querySelector(".element");
const keyframes = [
{ transform: "translate(0, 0)" },
{ transform: "translate(200px, 0)" },
{ transform: "translate(200px, 200px)" },
{ transform: "translate(0, 200px)"0 }
];
element.animate(keyframes, 4000);
Esto sería más o menos equivalente a cuando creamos una animación con CSS de la siguiente forma:
@keyframes move {
0% { transform: translate(0, 0); }
40% { transform: translate(200px, 0); }
60% { transform: translate(200px, 200px); }
80% { transform: translate(0, 200px); }
}
Si desconoces las animaciones CSS, sería aconsejable primero echar un vistazo antes de continuar, ya que vamos a asumir ciertos conocimientos: Aprender animaciones CSS.
En el ejemplo anterior habrás visto que hemos indicado una constante keyframes
, donde está toda la información de la animación. Ese objeto equivale a la regla @keyframes
de CSS con sus propiedades CSS en cada uno de los fotogramas clave o intervalos que componen la animación.
Ese parámetro puede pasarse al método .animate()
de dos formas. Vamos a analizar estas dos modalidades a continuación.
El parámetro keyframes
es un
const keyframes = [
{
transform: "translate(0, 0)",
opacity: 0,
backgroundColor: "#842911"
},
{
transform: "translate(200px, 0)",
opacity: 1
},
{
transform: "translate(200px, 200px)",
opacity: 0.25,
backgroundColor: "#840123"
},
{
transform: "translate(0, 200px)",
opacity: 1
}
];
Observa que cada propiedad de cada objeto es una propiedad CSS, pero escrita en camelCase. En el caso de transform
y opacity
no hace falta, pero en el caso de la propiedad background-color
, en este caso, se reescribe a backgroundColor
. Los valores normalmente son de tipo
El parámetro keyframes
también puede indicarse como un
const keyframes = {
transform: [
"translate(0, 0)",
"translate(200px, 0)",
"translate(200px, 200px)",
"translate(0, 200px)"
],
opacity: [0, 1, 0.25, 1],
backgroundColor: ["#842911", "#840123"]
};
La mecanica es la misma que la anterior, sólo que varía la forma de escribirlo. Utiliza la que mejor se adapte a tus necesidades.
Cada objeto de un fotograma clave o intervalo de la animación, a parte de las propiedades CSS transformadas a camelCase, puede tener alguna de las propiedades que comentaremos a continuación. Mediante ellas, podremos establecer particularidades a ese fotograma en cuestión:
Propiedades | Descripción |
---|---|
offset |
Indica el porcentaje de cada intervalo en los @keyframes de una animación CSS. |
easing |
Indica la función de tiempo que se aplicará al intervalo concreto de la animación. |
composite |
Indica la operación de composición que se aplicará en el resto de intervalos. |
La propiedad offset
nos permite indicar en que momento concreto empieza un intervalo o fotograma clave. Por otro lado, easing
nos permite activar una función de tiempo (ritmo) de la animación para un fotograma clave específico. Veremos que también se puede indicar en un objeto de opciones que explicaremos más adelante, y que afecte a todos los fotogramas clave de la animación.
Por último, tenemos composite
, que es una operación de composición para el fotograma clave concreto. Hablaremos de esta característica más adelante.
Probablemente, te hayas preguntando como puedes variar el instante en el que comienzan cada uno de los fotogramas clave de la animación. En CSS, estableciamos un porcentaje en el interior de las reglas @keyframes
que establecían este comienzo.
Aquí, esta información la establecemos en la propiedad offset
:
const element = document.querySelector(".element");
const keyframes = [
{ transform: "translate(0, 0)", offset: 0 },
{ transform: "translate(200px, 0)", offset: 0.40 },
{ transform: "translate(200px, 200px)", offset: 0.60 },
{ transform: "translate(0, 200px)", offset: 0.80 }
];
element.animate(keyframes, 4000);
Observa que en este fragmento de código, además de la propiedad transform
hemos establecido una propiedad offset
para determinar el inicio del fotograma. Dicha propiedad debe contener un valor 0
a 1
, con decimales. Esta es la equivalencia a los porcentajes. Por ejemplo, si tenemos 80%
en la regla @keyframes
, la equivalencia en este caso sería un offset
de 0.8
.
Las propiedades CSS
offset
yfloat
no se pueden definir ya que coinciden con la propiedadoffset
que acabamos de mencionar, y con la palabra reservadafloat
, por lo que si queremos establecerlas, debe hacerse comocssOffset
ycssFloat
.
Antes habrás comprobado que como segundo parámetro de animate()
establecíamos la duración de la animación. Sin embargo, en lugar de ese
Nuestro objeto de opciones podría tener las siguientes:
Propiedades | Descripción | Equivalencia CSS | Default |
---|---|---|---|
delay |
Tiempo (retardo) en ms para que empiece la animación. |
animation-delay |
0 |
endDelay |
Tiempo (retardo) en ms para finalizar la animación. |
— | 0 |
duration |
Duración en ms de la animación (por cada iteración). |
animation-duration |
auto |
direction |
Dirección de la animación por sus keyframes. | animation-direction |
normal |
easing |
Función de tiempo (ritmo) de la animación. | animation-timing-function |
linear |
fill |
Comportamiento de la animación al terminar. | animation-fill-mode |
auto |
iterationStart |
Punto de la iteración en la que empieza la animación. | — | 0.0 |
iterations |
Número de veces que se repite la animación. | animation-iteration-count |
1.0 |
iterationComposite |
Operación de composición entre cada intervalo. | — | replace |
composite |
Operación de composición entre una y otra animación. | animation-composition |
replace |
pseudoElement |
Si se indica ::before o ::after , se aplica la animación al pseudoelemento. |
Por si no los conoces, algunas propiedades anteriores pueden tomar varios valores posibles. Aquí puedes ver una lista de opciones posibles:
Propiedad | Valores |
---|---|
direction |
normal , reverse , alternate , alternate-reverse . |
easing |
linear , ease-in , ease-out , ease-in-out , cubic-bezier(...) . |
fill |
none , forwards , backwards , both , auto . |
composite |
add , accumulate , replace . |
iterationComposite |
accumulate , replace . |
Veamos ahora, un ejemplo utilizando el objeto de opciones en lugar del parámetro de duración directamente. Simplemente añadimos como segundo parámetro de animate()
el objeto de opciones:
const element = document.querySelector(".element");
const keyframes = [
{ transform: "translate(0, 0)", offset: 0 },
{ transform: "translate(200px, 0)", offset: 0.40 },
{ transform: "translate(200px, 200px)", offset: 0.60 },
{ transform: "translate(0, 200px)", offset: 0.80 }
];
const options = {
duration: 4000,
direction: "alternate",
fill: "forwards",
iterations: Infinity
};
const animation = element.animate(keyframes, options);
Recuerda que puedes utilizar cualquiera de los dos tipos de keyframes
que hemos explicado.
Animation
Habrás observado en el último ejemplo, que el valor devuelto por el método .animate()
lo estamos guardando en la constante animation
. Esta constante es un objeto Animation
, mediante el cuál podemos gestionar ciertas acciones con la animación generada en cuestión.
Entre otras cosas, podemos encontrar las siguientes propiedades:
Propiedad | Descripción |
---|---|
startTime |
Hora (timestamp) en la que la animación ha empezado o empezará a reproducirse. |
currentTime |
Número de ms en el que se encuentra la animación. Si está inactiva, null . |
id |
Cadena de texto para identificar la animación. |
finished |
Indica si la animación ha terminado. |
ready |
Indica si la animación está lista. |
pending |
Indica si la animación está pendiente y no está lista aún. |
playState |
Estado actual de la animación. Puede ser idle , running , paused o finished . |
playbackRate |
Velocidad de reproducción de la animación. Por defecto, 1 , velocidad normal. |
replaceState |
Indica estado de animación. Puede ser active , persisted o removed . |
Especialmente interesantes son las propiedades .ready
y finished
, que devuelven una promesa mediante la cuál podemos saber cuando una animación está lista para iniciarse o cuando ha terminado, y por ejemplo podemos encadenar con otra acción.
Por su parte, startTime
nos devuelve el momento en el que empezó a reproducirse (o una fecha en el futuro para programar la animación), mientras que currentTime
nos dice los segundos totales que han transcurrido de la animación:
const animation = element.animate(keyframes, options);
animation.ready.then(() => {
console.log(`¡Animación preparada!`);
});
animation.finished.then(() => {
console.log(`¡Animación terminada! Han pasado ${animation.currentTime}ms.`)
});
Mediante algunos métodos como play()
, pause()
, finish()
o cancel()
podemos controlar las animaciones, terminarlas o cancelarlas. Observa también que tienen algunos eventos asociados para detectar cuando ocurre.
Método | Descripción | Evento asociado |
---|---|---|
Métodos | ||
play() |
Inicia o reanuda la animación. | |
pause() |
Detiene temporalmente la animación. | |
finish() |
Termina la animación. | finish : Se dispara el evento al terminar la animación. |
cancel() |
Aborta la animación. | cancel : Se dispara el evento al abortar la animación. |
remove : Se dispara el evento al eliminar la animación automáticamente. |
||
persist() |
Indica que la animación sea persistente y no se elimine automáticamente al iniciar otra. | |
reverse() |
Invierte la dirección de reproducción. | |
updatePlaybackRate() |
Hace efectiva la velocidad de animación indicada en playbackRate . |
Observa que los navegadores por defecto, al tener animaciones encadenadas, al terminar una animación e iniciar otra, eliminan la anterior automáticamente. Cuando esto ocurre, se dispara un evento remove
que podemos utilizar para gestionar tareas cuando ocurren estas eliminaciones. Además, con el método persist()
podemos establecer que no se eliminen automáticamente.
Soy Manz, vivo en Tenerife (España) y soy streamer partner en Twitch y profesor. Me apasiona el universo de la programación web, el diseño y desarrollo web y la tecnología en general. Aunque soy full-stack, mi pasión es el front-end, la terminal y crear cosas divertidas y locas.
Puedes encontrar más sobre mi en Manz.dev