Basic animations

Esta traducción está incompleta. Por favor, ayuda a traducir este artículo del inglés.

Ya que estamos usando JavaScript para controlar los <canvas> , tambien es muy facil hacer animaciones (interactivos). En este capitulo veremos como hacer algunas animaciones basicas.

Probablemente la mayor limitacion es, que una vez que la forma se dibuja, quede asi. Y si tuvieramos que moverla tendriamos que redibujar todo y todo lo que fue dibujado antes. Esto tomaria mucho tiempo en redibujar (los marcos y las figuras complejas) y esto va a depender en gran medida de la velocidad a la que corra tu computadora.

Pasos para una Animacion Basica

Estos son los pasos que necesitas para dibujar un marco:

  1. Limpiar el Canva
    A menos que la forma que dibujes llene por completo el canva (Por Ejemplo una imagen de fondo), necesitas limpiar cualquier forma que hallas dibujado previamente. Esto facilemente podrias hacerlo usando el metodo clearRect().
  2. Guardar el estado del Canva
    Si tu modificas cualquier ajuste (como un estilo, transfomacion, etc.) que afecte estado del canva y quieres asegurarte que el estado original se use cada vez que dibujes un marco, entonces necesitas guardar el estado original.
  3. Dibujar formas animadas
    Este es le paso donde haces el renderizado del marco actual.
  4. Restaurar el estado del Canva
    Si tu has guardado el estado del canva, debes restaurarlo antes de dibujar un nuevo marco.

Controlar una Animacion

 

Para crear formas en en los canvas usamos los metodos de canvas o hacemos el llamando a funciones personalizadas. En un caso normal, nosostros solo vemos que el resultado aparece cuando el el script se ha ejecutado. Por ejemplo, no es posible hacer una animacion desde un bucle for.

Esto significa que necesitamos una manera de ejecutar nuestras funciones de dibujo en un período de tiempo.  Hay 2 formas para controlar una animacion como esta.

Actualizaciones Programadas

Primero window.setInterval(), window.setTimeout(), y window.requestAnimationFrame() son funciones que pueden ser usadas para llamar una funcion especifica en un periodo de tiempo establecido.

setInterval(function, delay)
Ejecuta una funcion especificada por function cada delay milisegundos.
setTimeout(function, delay)
Ejecuta una funcion especificada por function dentro de delay milisegundos.
requestAnimationFrame(callback)
Comunica al navegador que  deseas iniciar una animacion y requieres que el navegador llame a las funciones especificas para actualizar la misma antes de la siguiente escena.

Si no quieres ninguna interaccion del usuario puedes usar la funcion setInterval() que repite la ejecucion del codigo suminsitrado. Si lo que queremos es hacer un juego, nosotros usariamos los eventos del mouse o el teclado para controlar la animacion y usariamos setTimeout(). Al establecer los EventListener, capturamos cualquier interaccion del usuario y ejecutamos nuestras funciones de animacion.

En los siguiente ejemplo,usaremos el metodo para controlar animaciones window.requestAnimationFrame(). El metodo requestAnimationFrame provee formas amigables y mas eficientes  para animar llamando cada marco de animacion cuando el sistema esta listo para dibujar. Las retrollamadas son usualmente 60 veces por segundo y podria ser reducido a menor periodo cuando se corre en un segundo plano. Para mas informacion acerca de los ciclos de animacion, especialmente para juegos, Ver el Articulo Anatomia de un video juego en nuestra GameZona de desarrollo de Juegos.

Un sistema solar animado

Este ejemplo animado es un pequeño modelo de nuestro sistema solar

var sun = new Image();
var moon = new Image();
var earth = new Image();
function init(){
  sun.src = 'https://mdn.mozillademos.org/files/1456/Canvas_sun.png';
  moon.src = 'https://mdn.mozillademos.org/files/1443/Canvas_moon.png';
  earth.src = 'https://mdn.mozillademos.org/files/1429/Canvas_earth.png';
  window.requestAnimationFrame(draw);
}

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);

  // La tierra
  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);

  // La luna
  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);

  window.requestAnimationFrame(draw);
}

init();

ScreenshotLive sample

Un reloj animado

Este ejemplo dibuja una reloj animado, mostrando la hora actual.

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";

  // Aguja de la hora
  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();

  // Aguja del minuto
  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";

  // Escribimos la hora
  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();

  // escribimos los minutos
  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();
 
  // escribimos los segundos
  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();

  window.requestAnimationFrame(clock);
}

window.requestAnimationFrame(clock);

ScreenshotLive sample

Un ciclo Panoramico

En este ejemplo, una foto panoramica avanza de izquierda a derecha. Donde usaremos una imagen del Parque Nacional de Yosemite que tomamos de Wikipedia, pero tu podrias usar cualquier imagen que sea mas grande que el canva.

var img = new Image();

// Variables de usuario - personalizamos estas para cambiar la imagen cuando inicie el desplazamiento

// direccion y velocidad.

img.src = 'https://mdn.mozillademos.org/files/4553/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

// Program Base

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; }
    //Obtenemos el elemento canva
    ctx = document.getElementById('canvas').getContext('2d');
    //Establecemos la tasa de repeticiones
    return setInterval(draw, speed);
}

function draw() {
    //Limpiamos los Canvas
    ctx.clearRect(0,0,clearX,clearY);
    //If image is <= Canvas Size
    if (imgW <= CanvasXSize) {
        //reseteamos, iniciamos desde el principio
        if (x > (CanvasXSize)) { x = 0; }
        //dibujamos una imagen adicional
        if (x > (CanvasXSize-imgW)) { ctx.drawImage(img,x-CanvasXSize+1,y,imgW,imgH); }
    }
    //Si la imagen es > tamaño del Canvas
    else {
        //reseteamos, iniciamos desde el principio
        if (x > (CanvasXSize)) { x = CanvasXSize-imgW; }
        //dibujamos una imagen adicional
        if (x > (CanvasXSize-imgW)) { ctx.drawImage(img,x-imgW+1,y,imgW,imgH); }
    }
    //Dibujamos la imagen
    ctx.drawImage(img,x,y,imgW,imgH);
    //aumentamos al movimiento
    x += dx;
}

Debajo esta el elemento <canvas> en el cual va la imagen se va ha desplazar. Nota que el ancho y el alto especificado aqui son las variables CanvasXZSize y CanvasYSize.

<canvas id="canvas" width="800" height="200"></canvas>

Other examples

Un lanzador de rayos basico
Un buen ejemplo de como hacer animaciones usando como control el teclado
Animaciones avanzadas
Vamos a echar un vistazo a algunas técnicas de animación avanzadas y la física en el próximo capítulo.

Etiquetas y colaboradores del documento

 Colaboradores en esta página: Huarseral
 Última actualización por: Huarseral,