Basic animations
Já que estamos usando JavaScript para controlar <canvas>
elementos, também é muito fácil criar animações interativas. Fazer animações mais complexas pode levar um tempo extra; esperamos introduzir um novo artigo para auxiliar sobre isso em breve.
Provavelmente a maior limitação é que uma vez que uma forma é desenhada, ela permanece assim. Se precisarmos mover, temos que redesenhar-lá e tudo que foi desenhado antes. Demora muito tempo pra redesenhar frames complexos e a desempenho depende altamente da velocidade do computador em que está rodando.
Passos para animação básica
Estes são os passos que você precisa para desenhar um frame:
- Limpe o canvas A menos que a forma que você vai desenhar preencha o canvas completo(por exemplo, uma imagem de fundo), você precisa limpar todas as formas que foram desenhadas anteriormente. O caminho mais fácil para fazer isso é usando o método clearRect().
- Salve o estado da tela Se você estiver mudando alguma configuração(como estilos, transformações, etc.) que afete o estado do canvas e você quer garantir que o estado original seja usado sempre que um quadro é desenhado, você precisa salvar esse estado original.
- Desenhe formas animadas A etapa em que você faz a renderização real do quadro.
- Restaure o estado do canvas Se você salvou o estado, restaure-o antes de desenhar um novo quadro.
Controlando uma animação
Formas são desenhos na tela usando os canvas métodos diretamente ou chamando personalizadas. Em circunstancias normais, nós somente vemos esses resultados aparecerem na tela quando o script termina de ser executado. Por exemplo, não é possível fazer uma animação dentro de um loop for.
Isso significa que precisamos de um jeito para executar nossas funções de desenho durante um período de tempo. Existem dois jeitos para controlar uma animação como essa.
Atualizações agendadas
Primeiramente há as funções window.setInterval()
e window.setTimeout()
, que podem ser usadas para chamar uma função específica durante um certo período definido de tempo.
Nota:
Nota: O método window.requestAnimationFrame()
agora é a maneira recomendada de programar animações. Vamos atualizar esse tutorial para abortar isso em breve.
setInterval(função,atraso)
-
Inicia repetidamente executando a função específica pela função a cada milissegundo de atraso.
setTimeout(função,atraso)
-
Executa a função especificada pela função em milissegundos de atraso.
Se você não quer nenhuma interação do usuário, é melhor usar a função setInterval() que executa repeditamente o código fornecido.
Atualizar na interação do usuário
O segundo método que nós podemos usar para controlar uma animação é a entrada do usuário. Se nós quiséssimos criar um jogo, nós poderiamos usar os eventos do teclado ou mouse para controlar a animação. Ao definir EventListener
s, nós pegamos qualquer interação do usuário e executamos nossas funções da animação.
Se você quer a interação do usuário, você pode usar uma versão menor ou a versão principal do nosso framework pra animação:
var myAnimation = new MiniDaemon(null, animateShape, 500, Infinity);
ou
var myAnimation = new Daemon(null, animateShape, 500, Infinity);
Nos exemplos abaixo, no entanto, usamos o método window.setInterval()
para controlar a animação. Na parte inferior dessa página há alguns links de exemplos que usam window.setTimeout()
.
Um sistema solar animado
Esse exemplo anima um pequeno modelo do nosso sistema solar.
var sun = new Image();
var moon = new Image();
var earth = new Image();
function init() {
sun.src = "canvas_sun.png";
moon.src = "canvas_moon.png";
earth.src = "canvas_earth.png";
setInterval(draw, 100);
}
function draw() {
var ctx = document.getElementById("canvas").getContext("2d");
ctx.globalCompositeOperation = "destination-over";
ctx.clearRect(0, 0, 300, 300); // clear canvas
ctx.fillStyle = "rgba(0,0,0,0.4)";
ctx.strokeStyle = "rgba(0,153,255,0.4)";
ctx.save();
ctx.translate(150, 150);
// Earth
var time = new Date();
ctx.rotate(
((2 * Math.PI) / 60) * time.getSeconds() +
((2 * Math.PI) / 60000) * time.getMilliseconds(),
);
ctx.translate(105, 0);
ctx.fillRect(0, -12, 50, 24); // Shadow
ctx.drawImage(earth, -12, -12);
// Moon
ctx.save();
ctx.rotate(
((2 * Math.PI) / 6) * time.getSeconds() +
((2 * Math.PI) / 6000) * time.getMilliseconds(),
);
ctx.translate(0, 28.5);
ctx.drawImage(moon, -3.5, -3.5);
ctx.restore();
ctx.restore();
ctx.beginPath();
ctx.arc(150, 150, 105, 0, Math.PI * 2, false); // Earth orbit
ctx.stroke();
ctx.drawImage(sun, 0, 0, 300, 300);
}
Um relógio animado
Esse exemplos desenha um relógio animado, mostrando sua hora atual.
function init() {
clock();
setInterval(clock, 1000);
}
function clock() {
var now = new Date();
var ctx = document.getElementById("canvas").getContext("2d");
ctx.save();
ctx.clearRect(0, 0, 150, 150);
ctx.translate(75, 75);
ctx.scale(0.4, 0.4);
ctx.rotate(-Math.PI / 2);
ctx.strokeStyle = "black";
ctx.fillStyle = "white";
ctx.lineWidth = 8;
ctx.lineCap = "round";
// Hour marks
ctx.save();
for (var i = 0; i < 12; i++) {
ctx.beginPath();
ctx.rotate(Math.PI / 6);
ctx.moveTo(100, 0);
ctx.lineTo(120, 0);
ctx.stroke();
}
ctx.restore();
// Minute marks
ctx.save();
ctx.lineWidth = 5;
for (i = 0; i < 60; i++) {
if (i % 5 != 0) {
ctx.beginPath();
ctx.moveTo(117, 0);
ctx.lineTo(120, 0);
ctx.stroke();
}
ctx.rotate(Math.PI / 30);
}
ctx.restore();
var sec = now.getSeconds();
var min = now.getMinutes();
var hr = now.getHours();
hr = hr >= 12 ? hr - 12 : hr;
ctx.fillStyle = "black";
// write Hours
ctx.save();
ctx.rotate(
hr * (Math.PI / 6) + (Math.PI / 360) * min + (Math.PI / 21600) * sec,
);
ctx.lineWidth = 14;
ctx.beginPath();
ctx.moveTo(-20, 0);
ctx.lineTo(80, 0);
ctx.stroke();
ctx.restore();
// write Minutes
ctx.save();
ctx.rotate((Math.PI / 30) * min + (Math.PI / 1800) * sec);
ctx.lineWidth = 10;
ctx.beginPath();
ctx.moveTo(-28, 0);
ctx.lineTo(112, 0);
ctx.stroke();
ctx.restore();
// Write seconds
ctx.save();
ctx.rotate((sec * Math.PI) / 30);
ctx.strokeStyle = "#D40000";
ctx.fillStyle = "#D40000";
ctx.lineWidth = 6;
ctx.beginPath();
ctx.moveTo(-30, 0);
ctx.lineTo(83, 0);
ctx.stroke();
ctx.beginPath();
ctx.arc(0, 0, 10, 0, Math.PI * 2, true);
ctx.fill();
ctx.beginPath();
ctx.arc(95, 0, 10, 0, Math.PI * 2, true);
ctx.stroke();
ctx.fillStyle = "rgba(0,0,0,0)";
ctx.arc(0, 0, 3, 0, Math.PI * 2, true);
ctx.fill();
ctx.restore();
ctx.beginPath();
ctx.lineWidth = 14;
ctx.strokeStyle = "#325FA2";
ctx.arc(0, 0, 142, 0, Math.PI * 2, true);
ctx.stroke();
ctx.restore();
}
Um panorama em loop
Nesse exemplos, um panorama é rolado da esquerda pra direita. Nós estamos usando uma imagem do Parque Nacional de Yosemite que tiramos da Wikipedia, mas você pode usar qualquer imagem que fosse maior que a tela.
var img = new Image();
// User Variables - customize these to change the image being scrolled, its
// direction, and the speed.
img.src = "capitan_meadows,_yosemite_national_park.jpg";
var CanvasXSize = 800;
var CanvasYSize = 200;
var speed = 30; //lower is faster
var scale = 1.05;
var y = -4.5; //vertical offset
// Main program
var dx = 0.75;
var imgW;
var imgH;
var x = 0;
var clearX;
var clearY;
var ctx;
img.onload = function () {
imgW = img.width * scale;
imgH = img.height * scale;
if (imgW > CanvasXSize) {
x = CanvasXSize - imgW;
} // image larger than canvas
if (imgW > CanvasXSize) {
clearX = imgW;
} // image larger than canvas
else {
clearX = CanvasXSize;
}
if (imgH > CanvasYSize) {
clearY = imgH;
} // image larger than canvas
else {
clearY = CanvasYSize;
}
//Get Canvas Element
ctx = document.getElementById("canvas").getContext("2d");
//Set Refresh Rate
return setInterval(draw, speed);
};
function draw() {
//Clear Canvas
ctx.clearRect(0, 0, clearX, clearY);
//If image is <= Canvas Size
if (imgW <= CanvasXSize) {
//reset, start from beginning
if (x > CanvasXSize) {
x = 0;
}
//draw aditional image
if (x > CanvasXSize - imgW) {
ctx.drawImage(img, x - CanvasXSize + 1, y, imgW, imgH);
}
}
//If image is > Canvas Size
else {
//reset, start from beginning
if (x > CanvasXSize) {
x = CanvasXSize - imgW;
}
//draw aditional image
if (x > CanvasXSize - imgW) {
ctx.drawImage(img, x - imgW + 1, y, imgW, imgH);
}
}
//draw image
ctx.drawImage(img, x, y, imgW, imgH);
//amount to move
x += dx;
}
Abaixo é o <canvas>
em que a imagem é rolada. Note que a largura e a altura especificadas aqui devem corresponder aos valores das variáveis CanvasXZSize e CanvasYSize no código JavaScript.
<canvas id="canvas" width="800" height="200"></canvas>
Live sample
Outros exemplos
- Gartic
-
Jogo de desenho para multiplayers.
- Canvascape
-
Um jogo de aventura 3D (tiro em primeira pessoa).
- A basic ray-caster
-
Um bom exemplo de como fazer animações usando os controles do teclado.
- canvas adventure
-
Outro bom exemplo que usa controles de teclado.
- An interactive Blob
-
Divirta-se com Blob.
- Flying through a starfield
-
Voe através de estrelas, círculos ou quadrados.
- iGrapher
-
Um exemplo que ilustra os dados do mercado de ações.
Veja também
io error: No such file or directory (os error 2) (/home/runner/work/yari/yari/mdn/content/files/en-us/web/guide/html/canvas_tutorial/optimizing_canvas/index.md)