Como animar elementos gráficos da tela (HTML)

[ Este artigo destina-se aos desenvolvedores do Windows 8.x e do Windows Phone 8.x que escrevem aplicativos do Windows Runtime. Se você estiver desenvolvendo para o Windows 10, consulte documentação mais recente ]

O elemento de tela é uma região para desenho no documento HTML em que você pode usar o JavaScript para gerar gráficos como animações, gráficos e jogos. Esse tópico tem início através da descrição das etapas necessárias para animar um desenho básico usando o elemento de tela.

Pré-requisitos

Este tópico supõe que você:

  • Possa criar um aplicativo da Windows Store em JavaScript que use o modelo da Biblioteca do Windows para JavaScript.
  • Tenha noções básicas sobre HTML e JavaScript.

Para obter instruções sobre a criação do primeiro aplicativo da Windows Store em JavaScript, veja Criar o primeiro aplicativo da Windows Store em JavaScript. Para obter instruções sobre como usar o modelo WinJS, veja Como obter e usar o kit de ferramentas WinJS.

Instruções

Etapa 1: Tempo da animação

Usando o método requestAnimationFrame, você pode iniciar uma animação especificando uma função a ser chamada (retorno de chamada) sempre que for hora de atualizar a animação para a próxima ação de redesenhar:

requestAnimationFrame(animationFunction);

requestAnimationFrame leva em consideração a visibilidade da página e a taxa de atualização da tela para determinar quantos quadros por segundo devem ser alocados à animação (ou seja, chamar animationFunction).

Nosso exemplo em JavaScript desenha um círculo animado que realiza um movimento espiral ao redor de um círculo maior.

requestAnimationFrame(draw);

Aqui está nossa animação (os resultados podem variar; se o hardware for mais rápido, o ritmo dos círculos aumentará):

Um exemplo de um círculo espiral desenhado por uma animação de tela.

Etapa 2: Desenhar a imagem

  1. Limpar a tela

    Você precisa limpar a tela antes de desenhar cada quadro.

    Existem vários métodos para limpar uma tela, ou partes de uma imagem, como limpar determinadas áreas usando a propriedade globalCompositOperation ou recortando caminhos usando o método clip. A maneira mais simples para limpar uma tela é usar o método clearRect.

    No nosso exemplo, o método clearRect é usado para limpar a tela inteira, mas para facilitar a visualização dos efeitos do desenho da imagem, o método clearRect tem comentários. Se esta linha de código não tivesse comentários, você veria um único círculo em espiral em torno de uma órbita circular maior e seu rastro seria limpo antes de cada quadro ser desenhado.

    // The clearRect method clears the entire canvas.
    context.clearRect(0, 0, 160, 160);
    
  2. Salvar o estado da tela

    Ao desenhar sua imagem, você pode alterar algumas das configurações, como estilos ou transformações. Se você desejar usar as configurações originais quando começar cada redesenho de imagem, poderá usar o método save.

    Os métodos save e restore são usados para salvar e recuperar o estado da tela em uma pilha. O estado da tela consiste em todos os estilos e as transformações que foram aplicadas. Toda vez que o método save é chamado, o estado atual da tela é salvo na pilha. O método restore retorna o último estado salvo na pilha.

    No nosso exemplo, usamos o método save um pouco antes de definir algumas transformações para desenhar e mover o círculo animado.

    // Save the canvas state.
    context.save();
    
  3. Desenhar a imagem

    Enquanto desenha a imagem na tela, você pode usar duas transformações para fazer alterações na imagem; os métodos translate e rotate.

    O método translate é usado para mover a tela e sua origem para um ponto diferente na grade de tela:

    translate(x, y)
    

    Esse método aceita dois argumentos; x é a quantidade na qual a tela é movida para a esquerda ou direita e y é a quantidade que é movida para cima ou para baixo.

    É uma boa idéia salvar o estado da tela antes de fazer qualquer transformação, pois é mais fácil chamar o método restore do que ter que fazer uma conversão reversa para voltar a tela ao seu estado original. O método translate permite que você coloque a imagem em qualquer lugar da tela sem ter que ajustar manualmente as coordenadas.

    O método rotate é usado para girar a tela em torno da origem atual. Esse método tem apenas um parâmetro e é o ângulo no qual a tela é girada, medido em radianos.

    rotate(angle)
    

    A rotação move no sentido horário e o ponto central da rotação é sempre a origem da tela (no canto superior esquerdo). Para mover o ponto central, você precisará mover a tela usando o método translate.

    No nosso exemplo, alternaremos algumas chamadas para os métodos translate e rotate. A primeira chamada para o método translate centralizará a animação na tela.

    Em seguida, fazemos dois conjuntos de chamadas para os métodos rotate e translate. As primeiras chamadas para os métodos rotate e translate produzirá um pequeno círculo que é desenhado em torno da tela em um grande loop. O segundo conjunto de chamadas produzirá um círculo pequeno que é desenhado em uma órbita muito menor.

    O tamanho da tela é definido como 160 pixels de altura e 160 pixels de largura; por isso, definiremos as coordenadas x e y do método translate como 80 para que a nossa animação em geral esteja centralizada na tela.

    // centers the image on the canvas             
    context.translate(80, 80);
    

    Começamos nossa primeira chamada para o método rotate usando o objeto date para calcular o parâmetro do método rotate. Esse parâmetro é o ângulo no qual a tela será girada.

    var time = new Date();
    context.rotate( ((2*Math.PI)/60)*time.getSeconds() + ((2*Math.PI)/60000)*time.getMilliseconds() );
    

    Observe que o valor usado para calcular getSeconds é 60 e o valor para calcular getMilliseconds é de 60.000.

    O método translate move a coordenada x, que move o ciclo de rotação ao redor da tela em uma grande órbita.

    // Translate determines the size of the circle's orbit.
    context.translate(50, 0);
    

    Esse é o efeito dos primeiros métodos rotate e translate:

    Um grande círculo sem loops.

    As próximas duas chamadas para os métodos rotate e translate criam uma órbita menor de círculos em loop.

    // Rotate causes the circle to move in a small orbit.
    context.rotate( ((2*Math.PI)/6)*time.getSeconds() + ((2*Math.PI)/6000)*time.getMilliseconds() );
    
    // Translate determines the size of the orbit.
    context.translate(0, 5);
    

    Observe que, no cálculo do ângulo da segunda chamada de rotate, o valor usado para calcular getSeconds é 6 e o valor para calcular getMilliseconds é de 6.000.

    Se os primeiros métodos rotate e translate estiverem comentados, isto é o que os segundos métodos rotate e translate desenharão:

    Um círculo em loop.

    Depois que o reposicionamento é definido, o círculo é desenhado na tela.

    // This draws the repositioned circle
    context.beginPath();
    context.arc(5, 5, 4, 0, Math.PI*2, true); 
    context.stroke();
    
  4. Restaurar o estado da tela

    Salvamos o estado da tela posteriormente, na etapa b, assim temos agora o estado da tela para o próximo quadro a ser desenhado.

    // Restores the canvas to the previous state
    context.restore();
    

Exemplos completos

Gráficos animados

Este exemplo em JavaScript desenha um círculo animado que se move em movimento espiral ao redor de um círculo maior.

window.onload = init;
  
// As an optimization, make "context" a global variable that is only set once.
var context;
  
function init(){
  context = document.getElementById('canvas').getContext('2d');    
  window.requestAnimationFrame(draw);
} // init

function draw() {
  // Save the canvas state.
  context.save();         
  
  // context.clearRect(0, 0, 160, 160);

  // centers the image on the canvas             
  context.translate(80, 80); 
  
  // Rotate moves the spiraling circle around the canvas in a large orbit.
  var time = new Date();
  context.rotate( ((2*Math.PI)/60)*time.getSeconds() + ((2*Math.PI)/60000)*time.getMilliseconds() );
  
  // Translate determines the location of the small circle.
  context.translate(50, 0);  
  
  // Rotate causes the circle to spiral as it circles around the canvas.
  context.rotate( ((2*Math.PI)/6)*time.getSeconds() + ((2*Math.PI)/6000)*time.getMilliseconds() );
  
  // determines the size of the loop
  context.translate(0, 5);  
  
  // This draws the circle
  context.beginPath();
  context.arc(5, 5, 4, 0, Math.PI*2, true); 
  context.stroke();
  
  // Restores the canvas to the previous state
  context.restore();
  window.requestAnimationFrame(draw);
}  // draw

Trata-se de um exemplo de Folhas de estilos em cascata (CSS) que cria uma margem em preto próximo de um elemento de tela.

/* style the canvas element with a black border. */
canvas { border: 1px solid black; }

Esse arquivo HTML cria um elemento de tela e usa arquivos externos JavaScript e CSS.

<!DOCTYPE html>
<html>
    <head>
        <script type="text/javascript" src="myJavascript.js"></script>
        <link Rel="stylesheet" Href="myStyle.css" Type="text/css">
    </head>
    <body>
        <canvas id="canvas" width="160" height="160" />
    </body>
</html>

Tópicos relacionados

Guia rápido: desenhando em uma tela