Animação por tempo
A animação por tempo resulta de definir chaves (keys): Os valores de certos parâmetros em determinados instantes.
Por exemplo: A posição x = 1
no instante t = 0
e x = 2
no instante t = 2
.
É necessário calcular automaticamente os valores intermédios dos parâmetros que controlam uma animação.
Por exemplo:
- A posição de objeto é definida pelo parâmetro
x
. - É data a posição inicial:
x = 1
quandot = 0.5
. - E a posição final:
x = 2
quandot = 2.5
. - Sempre que necessário, pretende-se calcular as posições intermédias desse objeto.
Chaves | Valores Interpolados |
---|---|
|
|
As chaves definem os pontos «vermelhos»; o início e o fim. |
Os pontos «verdes» são calculados pela interpolação linear entre os pontos «vermelhos». |
Processo da Animação por Tempo
- São definidas chaves (keys) específicas.
- Cada chave define um instante e valores de parâmetros.
- Durante a animação:
- Os valores dos parâmetros são recalculados sempre que necessário.
- O modelo gráfico é atualizado com os novos valores dos parâmetros e construído/desenhado de novo.
A animação por tempo resolve o problema das diferenças de frequências que a animação por fotogramas coloca.
Sempre que o sistema gráfico está pronto para mostrar um novo fotograma, os valores dos parâmetros são recalculados; o modelo gráfico é atualizado com os novos valores dos parâmetros e desenhado de novo.
Isto significa que a definição de uma animação é feita através de modelo e esse modelo tem parâmetros que definem cada «fotograma» na sequência.
Modelos e Parâmetros
- Modelo
- Conjunto de variáveis (parâmetros) que definem cada «fotograma» na sequência.
- Parâmetro
- Variável que define um elemento da animação.
Exemplos de Modelos e Parâmetros
-
Um quadrado vermelho desloca-se da esquerda para a direita. Neste caso o modelo necessita apenas de um parâmetro, a abcissa () do quadrado:
const model = { x: 0 };
-
Um quadrado vermelho desloca-se na horizontal e na vertical. O modelo necessita de dois parâmetros, a abcissa () e a ordenada () do quadrado:
const model = { x: 0, y: 0 };
-
Um quadrado desloca-se na horizontal, na vertical e pode mudar de cor:
const model = { x: 0, y: 0, color: 'crimson' };
-
Vários quadrados deslocam-se na horizontal, na vertical e podem mudar a cor:
const model = { my_squares: [ { x: 0, y: 0, color: 'crimson' }, { x: 0, y: 8, color: 'khaki' } ] };
Tweens
Os tweens (contração do inglês «in-between») assentam uma técnica simples mas flexível e eficiente para:
- calcular os valores intermédios entre
- um valor inicial e
- um valor final durante
- um certo intervalo de tempo .
O valor intermédio, , quando , é calculado usando a fórmula:
Um tween atualiza, ao longo de um certo intervalo de tempo , um valor que varia de quanto para quando .
Os parâmetros fundamentais de um tween são:
- Valor Inicial ()
- Em que valor começa a variação do parâmetro.
- Valor Final ()
- Em que valor termina a variação do parâmetro.
- Tempo Inicial ()
- Em que instante começa a variação do parâmetro.
- Tempo Final () ou Duração ()
- Em que instante termina a variação (tempo final) ou quanto tempo demora a variação (duração). A relação entre o tempo inicial, o tempo final e a duração é:
Os tweens são usados para fazer animações com modelos parametrizados.
Tipos de Tweens
Os tweens descritos acima são lineares: a variação do parâmetro é proporcional ao tempo decorrido.
function draw(c, m) {
c.fillStyle = "steelblue";
c.fillRect(0, 0, 480, 120);
c.fillStyle = "crimson";
c.fillRect(m.linear.x, 10, 40, 40);
c.fillStyle = "khaki";
c.fillRect(m.nonlinear.x, 70, 40, 40);
}
const context = document
.getElementById("anim:tween:1")
.getContext("2d");
const model = {
linear: {x: 10,},
nonlinear: {x: 10}
};
const linear = new TWEEN.Tween(model.linear)
.to({x: 430}, 2000)
.easing(TWEEN.Easing.Linear.None)
.yoyo(true)
.repeat(Infinity)
.start();
const cubic = new TWEEN.Tween(model.nonlinear)
.to({x: 430}, 2000)
.easing(TWEEN.Easing.Quadratic.InOut)
.yoyo(true)
.repeat(Infinity)
.start();
const step = function(ctx, mdl) {
TWEEN.update();
draw(ctx, mdl);
requestAnimationFrame(function () {
step(ctx, mdl)
});
}
step(context, model);
Para animações com «objetos naturais» este tipo de tween não funciona bem porque produz movimentos uniformes, com velocidade constante.
- O resultado é semelhante ao movimento dos robots nos filmes antigos, ou de segunda categoria e também de alguns estilos de dança.
Os movimentos naturais não são lineares. Alguns aceleram no início e travam no fim. Outros têm uma fase de «ganhar balanço». As variantes são muitas.
- Easing define a aceleração de um tween e, em geral, tem as algumas variantes bem definidas.
- Ease-In tipo de aceleração no início da variação.
- Ease-Out tipo de aceleração no fim da variação.
Suporte para Tweens
A biblioteca tween.js
proporciona um sistema flexível e eficiente para definir e usar tweens. Os tweens desta biblioteca:
- São construídos com um valor inicial, um valor final e uma duração.
- Aceitam uma grande variedade de easings.
- Podem ser operados de várias formas:
- yoyo: depois de atingir o valor final, o tween volta ao inicial.
- repetir: o tween é repetido um certo número de vezes.
- encadear: aplicar um segundo tween após a conclusão do primeiro.
- etc.
O Ciclo de Animação
Qualquer animação é um ciclo infinito de atualização (update) e construção (render) de um modelo.
Os ciclos de animação e o uso dos tweens têm essencialmente a mesma estrutura e podem ser facilmente unificados.
Ciclo de Animação | Ciclo dos Tweens |
---|---|
|
|
Programação Web e Ciclos Infinitos
No contexto da programação na Web
, os ciclos infinitos devem ser implementados com a função requestAnimationFrame
.
function draw(context, model) {
/// Desenha o modelo atualizado no contexto fornecido.
}
function update(model) {
// Por exemplo, usando TWEEN.update();
}
const model = {
// valores iniciais dos parâmetros;
};
const step = function(ctx, mdl) {
update(mdl); // Atualiza os parâmetros do modelo.
draw(ctx, mdl); // Desenha o modelo atualizado.
requestAnimationFrame(function () { // Repete o ciclo de animação.
step(ctx, mdl)
});
}
step(context, model); // Inicia o ciclo de animação.
A razão para fazer o ciclo de animação com a função requestAnimationFrame
é que, desta forma, o navegador pode pausar a execução do código JavaScript quando necessário.
Na versão seguinte versão alternativa, o ciclo de animação é implementado usando um ciclo while
infinito que bloqueia o navegador e portanto, deve ser evitado.
function draw(context, model) {
/// Desenha o modelo atualizado no contexto fornecido.
}
function update(model) {
// Por exemplo, usando TWEEN.update();
}
const model = {
// valores iniciais dos parâmetros;
};
// BAD BAD NOT GOOD
while (true) { // ** O NAVEGADOR FICA BLOQUEADO AQUI **
update(model); // Atualiza os parâmetros do modelo.
draw(context, model); // Desenha o modelo atualizado.
}