No início deste ano, o Chrome 36 lançou o método element.animate como parte da especificação mais ampla de animações da Web. Isso permite animações nativas eficientes escritas de forma imperativa, aos desenvolvedores a opção de criar animações e transições com a abordagem mais adequada para eles.
Para relembrar rapidamente, veja como você pode animar uma nuvem pela tela, com um callback quando terminar:
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);
};
Isso por si só é incrivelmente fácil e vale a pena considerar como parte de sua caixa de ferramentas ao criar animações ou transições de forma imperativa. No entanto, no Chrome 39, os recursos de controle de reprodução foram adicionados ao objeto AnimationPlayer
retornado por element.animate
. Antes, depois que uma animação era criada, só era possível chamar cancel()
ou detectar o evento de conclusão.
Essas adições de reprodução ampliam as possibilidades do que as animações da Web podem fazer, transformando-as em uma ferramenta de uso geral, em vez de serem prescritivas sobre transições, ou seja, "fixadas" ou predefinidas.
Pausar, voltar ou mudar a velocidade do vídeo
Vamos começar atualizando o exemplo acima para pausar a animação se a nuvem for clicada:
cloud.addEventListener('mousedown', function() {
player.pause();
});
Também é possível modificar a propriedade playbackRate
:
function changeWindSpeed() {
player.playbackRate *= (Math.random() * 2.0);
}
Também é possível chamar o método reverse()
, que normalmente é equivalente a inverter a playbackRate
atual (multiplicar por -1). No entanto, há alguns casos especiais:
Se a mudança causada pelo método
reverse()
fizer com que a animação em execução seja encerrada, ocurrentTime
também será invertido.Por exemplo, se uma animação nova for invertida, toda a animação será reproduzida de trás para frente.Se o player estiver pausado, a animação começará a ser reproduzida.
Como refinar o player
Um AnimationPlayer
agora permite que o currentTime
seja modificado enquanto uma animação está em execução. Normalmente, esse valor aumenta com o tempo (ou diminuirá, se o playbackRate
for negativo). Isso pode permitir que a posição de uma animação seja controlada externamente, talvez pela interação do usuário. Isso é comumente chamado de limpeza.
Por exemplo, se a página HTML representasse o céu e você quisesse que um gesto de arrasto mudasse a posição de uma nuvem em reprodução, seria possível adicionar alguns manipuladores ao 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;
});
À medida que você arrasta o cursor pelo documento, o currentTime
é alterado para refletir a distância do evento original. Você também pode retomar a exibição da animação quando o gesto terminar:
document.addEventListener('touchend', function(event) {
startEvent = null;
player.play();
});
Isso pode ser combinado com o comportamento reverso, dependendo de onde o mouse foi levantado da página (demonstração combinada).
Em vez de limpar uma AnimationPlayer
em resposta a uma interação do usuário, o currentTime
dela também pode ser usado para mostrar o progresso ou o status, por exemplo, para mostrar o status de um download.
O utilitário aqui é que um AnimationPlayer
permite que um valor seja definido e que a implementação nativa subjacente cuide da visualização do progresso. No caso do download, a duração de uma animação pode ser definida como o tamanho total do download, e a currentTime
pode ser definida como o tamanho do download atual (demonstração).
Transições e gestos da interface
As plataformas móveis sempre foram o reino dos gestos comuns: arrastar, deslizar, deslizar rapidamente e assim por diante. Esses gestos tendem a ter um tema comum: um componente de interface arrastável, como o "puxe para atualizar" de uma visualização de lista ou uma barra lateral que aparece do lado esquerdo da tela.
Com animações da Web, é muito fácil replicar um efeito semelhante aqui na Web, no computador ou no dispositivo móvel. Por exemplo, quando um gesto que controla currentTime
é concluído:
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;
});
Isso cria uma animação extra que realiza uma "deriva". Isso é reproduzido entre onde o gesto foi concluído até nosso alvo conhecido.
Isso funciona porque as animações têm uma prioridade com base na ordem de criação. Neste caso, driftPlayer
tem precedência sobre o jogador. Quando driftPlayer
for concluído, ele e os efeitos dele vão desaparecer. No entanto, o tempo final vai corresponder ao currentTime do jogador, para que a interface continue consistente.
Por fim, se você gosta de gatinhos, há um aplicativo de demonstração da Web que mostra esses gestos. Ele é compatível com dispositivos móveis e usa o polyfill para compatibilidade com versões anteriores. Portanto, tente carregá-lo no seu dispositivo móvel.
Vá em frente e use element.animate
O método element.animate
é totalmente incrível agora, seja para animações simples ou para aproveitar o AnimationPlayer
retornado de outras maneiras.
Esses dois recursos também têm suporte total em outros navegadores modernos por meio de um polyfill leve. Esse polyfill também realiza a detecção de recursos. Portanto, à medida que os fornecedores de navegadores implementam a especificação, esse recurso só vai ficar mais rápido e melhor com o tempo.
A especificação do Web Animations também vai continuar a evoluir. Se você quiser testar os próximos recursos, eles também estão disponíveis em um polyfill mais detalhado: web-animations-next.