A principios de este año, Chrome 36 introdujo el método element.animate como parte de la especificación de animaciones web más amplia. Esto permite crear animaciones nativas eficientes escritas de forma imperativa, lo que les da a los desarrolladores la opción de crear sus animaciones y transiciones con el enfoque más adecuado.
Para repasar rápidamente, aquí te mostramos cómo puedes animar una nube en la pantalla, con una devolución de llamada cuando finalices:
var player = cloud.animate([
{transform: 'translateX(' + start + 'px)'},
{transform: 'translateX(' + end + 'px)'}
], 5000);
player.onfinish = function() {
console.info('Cloud moved across the screen!');
startRaining(cloud);
};
Esto por sí solo es increíblemente fácil y vale la pena tenerlo en cuenta como parte de tu caja de herramientas cuando compilas animaciones o transiciones de manera imperativa. Sin embargo, en Chrome 39, se agregaron funciones de control de reproducción al objeto AnimationPlayer
que muestra element.animate
. Anteriormente, una vez que se creaba una animación, solo se podía llamar a cancel()
o escuchar el evento de finalización.
Estas adiciones de reproducción abren las posibilidades de lo que Web Animations puede hacer: convertir animaciones en una herramienta de uso general, en lugar de ser prescriptivas sobre transiciones, es decir, 'corregido' o animaciones predefinidas.
Pausar, retroceder o cambiar la velocidad de reproducción
Comencemos por actualizar el ejemplo anterior para pausar la animación si se hace clic en la nube:
cloud.addEventListener('mousedown', function() {
player.pause();
});
También puedes modificar la propiedad playbackRate
:
function changeWindSpeed() {
player.playbackRate *= (Math.random() * 2.0);
}
También puedes llamar al método reverse()
, que normalmente equivale a invertir el playbackRate
actual (multiplica por -1). Sin embargo, existen algunos casos especiales:
Si el cambio causado por el método
reverse()
hace que la animación en ejecución finalice efectivamente,currentTime
también se invierte.Por ejemplo, si se invierte una animación completamente nueva, toda la animación se reproducirá hacia atrás.Si el reproductor está en pausa, la animación comenzará a reproducirse.
Arrastrar el reproductor
Un AnimationPlayer
ahora permite que se modifique su currentTime
mientras se ejecuta una animación. Por lo general, este valor aumentará con el tiempo (o disminuirá si el playbackRate
es negativo). Esto podría permitir que la posición de una animación se controle externamente, quizás a través de la interacción del usuario. Esto se conoce comúnmente como limpieza.
Por ejemplo, si tu página HTML representaba el cielo y deseas realizar un gesto de arrastre para cambiar la posición de una nube que se está reproduciendo, podrías agregar algunos controladores al documento:
var startEvent, startEventTime;
document.addEventListener('touchstart', function(event) {
startEvent = event;
startEventTime = players.currentTime;
player.pause();
});
document.addEventListener('touchmove', function(event) {
if (!startEvent) return;
var delta = startEvent.touches[0].screenX -
event.changedTouches[0].screenX;
player.currentTime = startEventTime + delta;
});
A medida que arrastres el documento, se modificará el valor de currentTime
para reflejar la distancia del evento original. También puedes reanudar la reproducción de la animación cuando finalice el gesto:
document.addEventListener('touchend', function(event) {
startEvent = null;
player.play();
});
Esto incluso podría combinarse con el comportamiento de inversión, según el lugar desde el que se quitó el mouse de la página (demostración combinada).
En lugar de borrar una AnimationPlayer
en respuesta a una interacción del usuario, su currentTime
también se podría usar para mostrar el progreso o el estado; por ejemplo, para mostrar el estado de una descarga.
La utilidad aquí es que un AnimationPlayer
permite que se establezca un valor y que la implementación nativa subyacente se encargue de la visualización del progreso. En el caso de descarga, la duración de una animación se podría establecer en el tamaño de descarga total y el currentTime
en el tamaño de descarga actual (demostración).
Transiciones y gestos de la IU
Las plataformas móviles han sido durante mucho tiempo el dominio de los gestos comunes: arrastrar, deslizar, arrastrar y demás. Estos gestos suelen tener un tema común: un componente de IU arrastrable, como la función "extraer para actualizar" de una vista de lista. o una barra lateral que se expande desde el lado izquierdo de la pantalla.
Con Web Animations, es muy fácil replicar un efecto similar aquí en la web, en computadoras de escritorio o dispositivos móviles. Por ejemplo, cuando se completa un gesto que controla currentTime
:
var steps = [ /* animation steps */ ];
var duration = 1000;
var player = target.animate(steps, duration);
player.pause();
configureStartMoveListeners(player);
var setpoints = [0, 500, 1000];
document.addEventListener('touchend', function(event) {
var srcTime = player.currentTime;
var dstTime = findNearest(setpoints, srcTime);
var driftDuration = dstTime - srcTime;
if (!driftDuration) {
runCallback(dstTime);
return;
}
var driftPlayer = target.animate(steps, {
duration: duration,
iterationStart: Math.min(srcTime, dstTime) / duration,
iterations: Math.abs(driftDuration) / duration,
playbackRate: Math.sign(driftDuration)
});
driftPlayer.onfinish = function() { runCallback(dstTime); };
player.currentTime = dstTime;
});
Esto crea una animación adicional que realiza un "desvío". Esto se reproduce entre el lugar donde se completó el gesto y hasta nuestro buen objetivo conocido.
Esto funciona porque las animaciones tienen una prioridad según su orden de creación: en este caso, driftPlayer
tendrá prioridad sobre el reproductor. Cuando se complete driftPlayer
, desaparecerán junto con sus efectos. Sin embargo, su hora final coincidirá con el tiempo actual del jugador subyacente, por lo que tu IU se mantendrá coherente.
Por último, si le gustan los gatitos, hay una aplicación web de demostración que muestra estos gestos. Está optimizado para dispositivos móviles y usa polyfill para ofrecer retrocompatibilidad, así que intenta cargarlo en tu dispositivo móvil.
Adelante y element.animate.
El método element.animate
se ve completamente en este momento, ya sea que lo uses para animaciones simples o que aproveches de otras maneras su AnimationPlayer
que se muestra.
Estas dos funciones también son totalmente compatibles con otros navegadores modernos mediante un polyfill liviano. Este polyfill también realiza una detección de funciones, por lo que, a medida que los proveedores de navegadores implementen la especificación, mejorará y acelerada cada vez más con el tiempo.
La especificación de Web Animations también seguirá evolucionando. Si te interesa explorar las próximas funciones, también están disponibles en un polyfill más detallado: web-animations-next.