Creando animaciones con canvas, javascript y HTML5.

5 de noviembre de 2016

CANVAS es una alternativa para crear animaciones interactivas y multiplataforma que funcionen en dispositivos móviles y computadoras de escritorio.

Contenido

Introducción

En el año 2010 Steve Jobs le declaró la guerra a Adobe Flash para apoderarse del mercado y los dólares de las rich internet applications. Como alternativa a Adobe Flash Steve Jobs sugirió utilizar la naciente tecnología de CANVAS o crear una app con código nativo (donde el pago de la licencia va para Apple y por cada venta Apple se lleva su comisión)

Ahora en el año 2016, ya sin soporte para Adobe Flash en los dispositivo móviles, hay varias alternativas para crear animaciones multiplataforma:

En estos 6 años han surgido animaciones y videojuegos hechos con canvas bastante interesantes. Tenemos por ejemplo:

La facilidad de uso y el poder de Adobe Flash produjeron en su tiempo un auge en el desarrollo de videojuegos. Casi cualquiera podía hacer su videojuego. Adobe Flash liberó el potencial creativo de miles de personas a lo largo del mundo.

Con CANVAS las cosas son diferentes... ni es tan fácil ni tan poderoso como Adobe Flash.

Comienzan a surgir programas que permiten animar en CANVAS, tenemos por ejemplo:

Durante varios años google ofreció swiffy, una herramienta para convertir animaciones en Flash en animaciones en CANVAS. Desafortunadamente en el año 2016 Google descontinuó el servicio y dejó a muchos usuarios huérfanos.

Para animar en CANVAS se necesita javascript. Todo se crea con javascript. Javascript es a CANVAS, lo que ActionScript era a Adobe Flash.

Crear un canvas

CANVAS utiliza un elemento nuevo de HTML5:

<canvas></canvas>

Con ayuda de los atributos width y height podemos definir el ancho y el alto de nuestro CANVAS:

<canvas width="450" height="202"></canvas>

Es conveniente asignar un atributo id a nuestro elemento canvas, con ello podremos referirnos a él y utilizarlo desde javascript:

<canvas id="canvas" width="450" height="202"></canvas>

Agregaremos un marco de color con CSS a nuestro CANVAS para distinguirlo:

<canvas id="canvas" width="450" height="202" style="border:3px solid #ccc;"></canvas>

Insisto nuevamente: para crear animaciones en canvas necesitamos javascript. En el head de nuestro documento debemos insertar el código javascript para crear nuestra animación:

<head> <script> </script> </head>

Lo primero que debemos cerciorarnos es que la página ha cargado por completo. Cuando la página ha cargado, podemos comenzar a crear nuestra animación. Para ello se utilizará este código:

<script> window.onload = function() // esto es un comentario en javascript // aquí creamos una función // cuando la página se cargue, ejecutamos el siguiente código { animacion_con_canvas(); // cuando la página se cargue, ejecutamos otra función animacion_con_canvas(); } </script>

El código completo para crear un CANVAS sería:

<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <script> window.onload = function() // esto es un comentario en javascript // aqui creamos una función // cuando la página se cargue, ejecutarmos el siguiente código { animacion_con_canvas(); // cuando la página se cargue, ejecutarmos otra función animacion_con_canvas(); } function animacion_con_canvas() // creamos la función animacion_con_canvas { var mi_canvas = document.getElementById("canvas"); // el elemento bautizado "canvas" sera usado para crear la animaciòn var contexto = mi_canvas.getContext("2d"); // creamos el objeto contexto para poder animar en canvas // contexto es un objeto. Como todo objeto tiene propiedades métodos y eventos // canvas soporta animaciones en 2d y en 3d, en este ejemplo usaremos animaciones 2d } </script> </head> <body> <canvas id="canvas" width="450" height="202" style="border:3px solid #ccc;"> Tu navegador no soporta canvas </canvas> </body> </html>

El resultado de este ejercicio se puede ver aquí: Mi primer canvas.

¿Dónde están las explosiones? ¿Dónde está la animación? ¡Devúelvanme mi dinero! Por ahora hemos sólo hemos creado nuestro CANVAS.

Dibujar en canvas

CANVAS tienes métodos que permite dibujar líneas, parábolas, rectángulos, cuadrados, círculos, etc..

Para dibujar un círculo, un rectángulo o una línea podemos usar los métodos, propiedades y eventos del objet context.

Para dibujar un círculo el código necesario es:

contexto.strokeStyle = "black"; // contexto es un objeto. Como todo objeto tiene propiedades métodos y eventos // aqui utilizamo la propiedad strokeStyle para definir el color del contorno del objeto a dibujar // el valor asignado es un color en el formato rgb contexto.lineWidth = 5; // aqui utilizamo la propiedad lineWidth para definir el ancho del contorno del objeto a dibujar // el valor asignado es un número entero y se traduce en pixeles contexto.arc(100, 100, 20, (Math.PI/180)*0, (Math.PI/180)*360, false); // aqui utilizamo el método arc para crear un círculo // el método arc se utiliza para crear parábolas, pero con los parámetros suficientes se puede crear un círculo // el método arc utiliza las variables: // (posición en x, posición en y, radio / tamaño del círculo, ángulo incial, ángulo final, sentido del arco a dibujar) contexto.stroke(); // utiliza el metodo stroke para mostrar en el cavas nuestro círculo

El código completo para dibujar un círculo en nuestro CANVAS sería:

<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <script> window.onload = function() // esto es un comentario en javascript // aqui creamos una función // cuando la página se cargue, ejecutarmos el siguiente código { animacion_con_canvas(); // cuando la página se cargue, ejecutarmos otra función animacion_con_canvas(); } function animacion_con_canvas() // creamos la función animacion_con_canvas { var mi_canvas = document.getElementById("canvas"); // el elemento bautizado "canvas" sera usado para crear la animaciòn var contexto = mi_canvas.getContext("2d"); // creamos el contexto para poder animar en canvas // canvas soporta animaciones en 2d y en 3d, en este ejemplo usaremos animaciones 2d contexto.strokeStyle = "black"; // contexto es un objeto. Como todo objeto tiene propiedades métodos y eventos // aqui utilizamo la propiedad strokeStyle para definir el color del contorno del objeto a dibujar contexto.lineWidth = 5; // aqui utilizamo la propiedad lineWidth para definir el ancho del contorno del objeto a dibujar contexto.arc(100, 100, 20, (Math.PI/180)*0, (Math.PI/180)*360, false); // aqui utilizamo el método arc para crear un círculo // el método arc se utiliza para crear parábolas, pero con los parámetros suficientes se puede crear un círculo // el método arc utiliza las variables //(posición en x, posición en y, radio / tamaño del círculo, ángulo incial, ángulo final, sentido del arco a dibujar) contexto.stroke(); // utiliza el metodo stroke para mostrar en el cavas nuestro círculo } </script> </head> <body> <canvas id="canvas" width="450" height="202" style="border:3px solid #ccc;"> Tu navegador no soporta canvas </canvas> </body> </html>

El resultado de este ejercicio se puede ver aquí: Dibujando un círculo en CANVAS.

Insertar una imagen en canvas

Se pueden insertar imágenes jpg, png o svg en nuestro CANVAS. Incluso es posible insertar vídeos en formato .mp4 u .ogg. Más aún, se puede extraer un cuadro / frame de un vídeo e insertarlo en el CANVAS.

Para insertar imágenes jpg, png o svg el código necesario es:

var img_palomita = new Image(); // creamos un objeto del tipo imagen // Como todo objeto tiene propiedades métodos y eventos img_palomita.src ="./i/canvas/01.png"; // con la propiedad src definimos la imagen a cargar. DEBE ESCRIBIRSE LA RUTA CORRECTA A LA IMAGEN img_palomita.addEventListener('load', mostrar_imagen, false); // para poder mostrar la imagen, primero debe cargarse... // la imagen tienen el evento load, que se produce cuando la imagen se ha descargado en el navegador // el método EventListener permite verificar cuando la imagen se ha cargado // cuando la imagen se ha cargado ejecutaremos la función mostrar_imagen, que mostrará la imágen en el canvas // el método EventListener utiliza las variables (evento, función a ejecutar, indica si se desea iniciar el registro del evento) function mostrar_imagen() // creamos la función mostrar_imagen para mostrar la imagen en el canvas // esta función se ejecuta cuando la imagen se ha cargado { contexto.drawImage(img_palomita, 309, 21); // aqui utilizamo el método drawimage para mostrar a nuestra imagen dentro del canvas // el método drawimage utiliza las variables (imagen a cargar, posición en x, posición en y) // el método drawimage se puede usar indistintamente para cargar imágenes jpg, png o svg }

El código completo para insertar una imagen en nuestro CANVAS sería:

<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <script> window.onload = function() // esto es un comentario en javascript // aqui creamos una función // cuando la página se cargue, ejecutarmos el siguiente código { animacion_con_canvas(); // cuando la página se cargue, ejecutarmos otra función animacion_con_canvas(); } function animacion_con_canvas() // creamos la función animacion_con_canvas { var mi_canvas = document.getElementById("canvas"); // el elemento bautizado "canvas" sera usado para crear la animaciòn var contexto = mi_canvas.getContext("2d"); // creamos el contexto para poder animar en canvas // canvas soporta animaciones en 2d y en 3d, en este ejemplo usaremos animaciones 2d var img_palomita = new Image(); // creamos un objeto del tipo imagen // Como todo objeto tiene propiedades métodos y eventos img_palomita.src ="./i/canvas/01.png"; // con la propiedad src definimos la imagen a cargar. DEBE ESCRIBIRSE LA RUTA CORRECTA A LA IMAGEN img_palomita.addEventListener('load', mostrar_imagen, false); // para poder mostrar la imagen, primero debe cargarse... // la imagen tienen el evento load, que se produce cuando la imagen se ha descargado en el navegador // el método EventListener permite verificar cuando la imagen se ha cargado // cuando la imagen se ha cargado ejecutaremos la función mostrar_imagen, que mostrará la imágen en el canvas // el método EventListener utiliza las variables (evento, función a ejecutar, indica si se desea iniciar el registro del evento) function mostrar_imagen() // creamos la función mostrar_imagen para mostrar la imagen en el canvas // esta función se ejecuta cuando la imagen se ha cargado { contexto.drawImage(img_palomita, 309, 21); // aqui utilizamo el método drawimage para mostrar a nuestra imagen dentro del canvas // el método drawimage utiliza las variables (imagen a cargar, posición en x, posición en y) // el método drawimage se puede usar indistintamente para cargar imágenes jpg, png o svg } } </script> </head> <body> <canvas id="canvas" width="450" height="202" style="border:3px solid #ccc;"> Tu navegador no soporta canvas </canvas> </body> </html>

El resultado de este ejercicio se puede ver aquí: Insertando una imagen en canvas

Animar en canvas

¿Y que hay de la animación? En tiempos remotos se utilizaba el método setInterval() de javascript para hacer animaciones en canvas. Se lograba animar, pero era ineficiente.

Ahora se ha creado el método requestAnimationFrame(). Paradójicamente hay navegadores que pueden trabajar con CANVAS... pero no con requestAnimationFrame(). RequestAnimationFrame() intenta ejecutar una función 60 veces por segundo... si el navegador y el dispositivo utilizado lo permite.

CANVAS crea animaciones cuadro por cuadro, frame by frame. 100 años después de la invención del cine se sigue usando el mismo método para animar. Se dibuja un cuadro. Se dibuja otro cuadro. Se dibuja otro cuadro. Y así hasta el infinito. El secreto está en mostrar sucesivamente esos cuadros para crear la ilusión de animación. El método RequestAnimationFrame() intenta mostrar 60 cuadros por segundo. ¡Más rápido que el cine!

A continuación crearemos una animación sencilla. Una imagen la desplazaremos de izquierda a derecha. Para crear esa animación podríamos utilizar este código:

img_palomita.addEventListener('load', animar_imagen, false); // para poder mostrar la imagen, primero debe cargarse... // la imagen tienen el evento load, que se produce cuando la imagen se ha descargado en el navegador // el método EventListener permite verificar cuando la imagen se ha cargado // cuando la imagen se ha cargado ejecutaremos la función animar_imagen, que animará la imágen en el canvas // el método EventListener utiliza las variables (evento, función a ejecutar, indica si se desea iniciar el registro del evento) var xpos = 0; // posicion inicial de nuesto objeto a animar var velocidad = 0.16; // cuantos pixeles en 0.016 segundos avanzara nuestro objeto a animar // IMPORTANTE: requestAnimationFrame() se ejecuta 60 veces por segundo // aqui el objeto se animará 10 pixeles por segundo // 0.16 = 10 pixeles por segundo / 60 veces por segundo que se ejecuta requestAnimationFrame() // si queremos que nuesto objeto se mueva más rápido o lento, solo tenemos que modificar la velocidad function animar_imagen() // creamos la función mostrar_imagen para mostrar la imagen en el canvas // esta función se ejecuta cuando la imagen se ha cargado { fx_animar_imagen = requestAnimationFrame(animar_imagen); // invocamos la función requestAnimationFrame // requestAnimationFrame intenta ejecutar una función 60 veces por segundo // en este caso ejecutará la función animar_imagen // el método requestAnimationFrame utiliza las variables (función a ejecutar) contexto.fillStyle = "#ffffff"; // contexto es un objeto. Como todo objeto tiene propiedades métodos y eventos // aqui utilizamo la propiedad fillStyle para definir el color de fondo de objeto a dibujar contexto.fillRect(0, 0, 450, 202); // aqui utilizamo el método fillRect para crear un rectángulo // el método fillRect utiliza las variables (posición en x, posición en y, ancho, alto) // creamos un rectangulo para borrar el fondo // CANVAS crea animaciones cuadro por cuadro, frame by frame. // 100 años después se sigue usando el mismo método para animar. // Se dibuja un cuadro. Se dibuja otro cuadro. Se dibuja otro cuadro. Y así hasta el infinito. // El secreto está en mostrar sucesivamente esos cuadros para crear la ilusión de animación. // El método RequestAnimationFrame() intenta mostrar 60 cuadros por segundo. ¡Más rápido que el cine! // creamos un rectangulo para borrar el cuadro dibujado previamente por CANVAS contexto.drawImage(img_palomita, xpos, 21); // aqui utilizamo el método drawimage para mostrar a nuestra imagen dentro del canvas // el método drawimage utiliza las variables (imagen a cargar, posición en x, posición en y) // el método drawimage se puede usar indistintamente para cargar imágenes jpg, png o svg // aquí la posición en x cambiará dinámicamente xpos = xpos + velocidad; // aumentamos el valor de xpos con el valor de velocidad }

El código completo para insertar animar una imagen en nuestro CANVAS y animarla sería:

<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <script> window.onload = function() // esto es un comentario en javascript // aqui creamos una función // cuando la página se cargue, ejecutarmos el siguiente código { animacion_con_canvas(); // cuando la página se cargue, ejecutarmos otra función animacion_con_canvas(); } function animacion_con_canvas() // creamos la función animacion_con_canvas { var mi_canvas = document.getElementById("canvas"); // el elemento bautizado "canvas" sera usado para crear la animaciòn var contexto = mi_canvas.getContext("2d"); // creamos el contexto para poder animar en canvas // canvas soporta animaciones en 2d y en 3d, en este ejemplo usaremos animaciones 2d var img_palomita = new Image(); // creamos un objeto del tipo imagen // Como todo objeto tiene propiedades métodos y eventos img_palomita.src ="./i/canvas/01.png"; // con la propiedad src definimos la imagen a cargar. DEBE ESCRIBIRSE LA RUTA CORRECTA A LA IMAGEN img_palomita.addEventListener('load', animar_imagen, false); // para poder mostrar la imagen, primero debe cargarse... // la imagen tienen el evento load, que se produce cuando la imagen se ha descargado en el navegador // el método EventListener permite verificar cuando la imagen se ha cargado // cuando la imagen se ha cargado ejecutaremos la función mostrar_imagen, que mostrará la imágen en el canvas // el método EventListener utiliza las variables (evento, función a ejecutar, indica si se desea iniciar el registro del evento) var xpos = 0; // posicion inicial de nuesto objeto a animar var velocidad = 0.16; // cuantos pixeles en 0.016 segundos avanzara nuestro objeto a animar // IMPORTANTE: requestAnimationFrame() se ejecuta 60 veces por segundo // aqui el objeto se animará 10 pixeles por segundo // 0.16 = 10 pixeles por segundo / 60 veces por segundo que se ejecuta requestAnimationFrame() // si queremos que nuesto objeto se mueva más rápido o lento, solo tenemos que modificar la velocidad function animar_imagen() // creamos la función mostrar_imagen para mostrar la imagen en el canvas // esta función se ejecuta cuando la imagen se ha cargado { fx_animar_imagen = requestAnimationFrame(animar_imagen); // invocamos la función requestAnimationFrame // requestAnimationFrame intenta ejecutar una función 60 veces por segundo // en este caso ejecutará la función animar_imagen // el método requestAnimationFrame utiliza las variables (función a ejecutar) contexto.fillStyle = "#ffffff"; // contexto es un objeto. Como todo objeto tiene propiedades métodos y eventos // aqui utilizamo la propiedad fillStyle para definir el color de fondo de objeto a dibujar contexto.fillRect(0, 0, 450, 202); // aqui utilizamo el método fillRect para crear un rectángulo // el método fillRect utiliza las variables (posición en x, posición en y, ancho, alto) // creamos un rectangulo para borrar el fondo // CANVAS crea animaciones cuadro por cuadro, frame by frame. // 100 años después se sigue usando el mismo método para animar. // Se dibuja un cuadro. Se dibuja otro cuadro. Se dibuja otro cuadro. Y así hasta el infinito. // El secreto está en mostrar sucesivamente esos cuadros para crear la ilusión de animación. // El método RequestAnimationFrame() intenta mostrar 60 cuadros por segundo. ¡Más rápido que el cine! // creamos un rectangulo para borrar el cuadro dibujado previamente por CANVAS contexto.drawImage(img_palomita, xpos, 21); // aqui utilizamo el método drawimage para mostrar a nuestra imagen dentro del canvas // el método drawimage utiliza las variables (imagen a cargar, posición en x, posición en y) // el método drawimage se puede usar indistintamente para cargar imágenes jpg, png o svg // aquí la posición en x cambiará dinámicamente xpos = xpos + velocidad; // aumentamos el valor de xpos con el valor de velocidad } } </script> </head> <body> <canvas id="canvas" width="450" height="202" style="border:3px solid #ccc;"> Tu navegador no soporta canvas </canvas> </body> </html>

El resultado de este ejercicio se puede ver aquí: animar una imagen en CANVAS.

Para los curiosos: ¿Que pasaría si no borramos el cuadro previamente dibujado por CANVAS? El resultado de este ejercicio se puede ver aquí: animar una imagen en CANVAS sin borrar el cuadro previo.

Animaciones sucesivas e interactivas en canvas

Con CANVAS se pueden crear animaciones sucesivas, interactivas y que simulen escenas como en Adobe Flash. El resultado de este ejercicio se puede ver aquí: Animación sucesiva e interactivas en canvas

El código fuente de esta animación es:

<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Animaciones Sucesivas</title> <script> window.onload = function() { animacion_con_canvas(); } function animacion_con_canvas() { var mi_canvas = document.getElementById("canvas"); var contexto = mi_canvas.getContext("2d"); var xpos = 0; var img_fondo = new Image(); var img_palomita = new Image(); var img_encuesta = new Image(); var img_clima = new Image(); var img_fecha = new Image(); var img_participa = new Image(); img_fondo.src ="./i/canvas/00.png"; img_palomita.src ="./i/canvas/01.png"; img_encuesta.src ="./i/canvas/02.png"; img_clima.src ="./i/canvas/03.png"; img_fecha.src ="./i/canvas/04.png"; img_participa.src ="./i/canvas/05.png"; var intro_alpha =0; var alpha_velocidad = 0.0055555556; // velocidad para aparecer // requestAnimationFrame muestra 60 frames por segundo // 60 frames = 1 segundo // 600 frames = 10 segundos // 1 (alpha full) / 180 (frames _ 3 segundos) = 0.0055555556 var pausa_en_stage = 5000; // velocidad para quedarse en pantalla img_participa.addEventListener('load', iniciar_animacion, false); // valida que la imagen se haya cargado // ejecuta la función iniciar_animacion function iniciar_animacion() { intro_in(); // ejecuta la funcion intro_in } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // muestra fondo // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * function muestra_fondo() { contexto.fillStyle = "#ffffff"; // borra el fondo contexto.fillRect(0, 0, 450, 202); // crea un rectangulo para borrar el fondo contexto.drawImage(img_fondo, 0, 0); contexto.drawImage(img_palomita, 309, 21); } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // intro alpha in // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * function intro_in() { intro_in_fx = requestAnimationFrame(intro_in); muestra_fondo(); contexto.save(); // guarda el canvas como esta // aplicamos cambios contexto.globalAlpha = intro_alpha; contexto.drawImage(img_encuesta, 15, 63); contexto.drawImage(img_clima, -1, 102); intro_alpha = intro_alpha + alpha_velocidad; contexto.restore(); // despues de hacer los cambios // restauramos el canvas guardado if(intro_alpha > 1) { intro_alpha = 0; window.cancelAnimationFrame(intro_in_fx); // elimina la animación intro_estatica(); // muestra las cosas sin movimiento... } } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // intro estatica // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * function intro_estatica() { muestra_fondo(); contexto.drawImage(img_encuesta, 15, 63); contexto.drawImage(img_clima, -1, 102); timeout_intro_estatica = window.setTimeout(kill_timeout_intro_estatica, pausa_en_stage); // en 5 segundos se ejecutara kill_timeout_intro_estatica } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // kill_timeout_intro_estatica // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * function kill_timeout_intro_estatica() { window.clearTimeout(timeout_intro_estatica); // destruye el timeout fecha_in(); // ejecuta la siguiente función // durante n tiempo } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // intro fecha alpha in // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * function fecha_in() { fx_fecha_in = requestAnimationFrame(fecha_in); muestra_fondo(); contexto.save(); // guarda el canvas como esta // aplicamos cambios contexto.globalAlpha = intro_alpha; contexto.drawImage(img_fecha, 21, 44); intro_alpha = intro_alpha + alpha_velocidad; contexto.restore(); // despues de hacer los cambios // restauramos el canvas guardado if(intro_alpha > 1) { intro_alpha = 0; window.cancelAnimationFrame(fx_fecha_in); // elimina la animación fecha_estatica(); // muestra las cosas sin movimiento... } } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // intro fecha estática // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * function fecha_estatica() { muestra_fondo(); contexto.drawImage(img_fecha, 21, 44); timeout_fecha_estatica = window.setTimeout(kill_fecha_estatica, pausa_en_stage); // en 5 segundos se ejecutara kill_fecha_estatica // setTimeout(función a ejecutarse, en cuanto tiempo) } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // kill_fecha_estatica // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * function kill_fecha_estatica() { window.clearTimeout(timeout_fecha_estatica); // destruye el timeout participa_in(); // ejecuta la siguiente función // durante n tiempo } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // intro participa alpha in // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * function participa_in() { fx_participa_in = requestAnimationFrame(participa_in); muestra_fondo(); contexto.save(); // guarda el canvas como esta // aplicamos cambios contexto.globalAlpha = intro_alpha; contexto.drawImage(img_participa, 10, 74); intro_alpha = intro_alpha + alpha_velocidad; contexto.restore(); // despues de hacer los cambios // restauramos el canvas guardado if(intro_alpha > 1) { intro_alpha = 0; window.cancelAnimationFrame(fx_participa_in); // elimina la animación participa_estatica(); // muestra las cosas sin movimiento... } } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // intro participa_estatica // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * function participa_estatica() { muestra_fondo(); contexto.drawImage(img_participa, 10, 74); timeout_participa_estatica = window.setTimeout(kill_participa_estatica, pausa_en_stage); // en 5 segundos se ejecutara kill_fecha_estatica // setTimeout(función a ejecutarse, en cuanto tiempo) } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // kill_participa_estatica // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * function kill_participa_estatica() { window.clearTimeout(timeout_participa_estatica); // destruye el timeout intro_in(); // ejecuta la siguiente función } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // al hacer click... // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * function al_hacer_click(e) { window.location.href = 'http://www.alaingarcia.net/'; } mi_canvas.addEventListener("click", al_hacer_click, false); // crea el botón... // onMouseClick el nombre de la función a ejecutarse } </script> </head> <body> <canvas id="canvas" width="450" height="202" style="cursor:pointer; border:3px solid #ccc; cursor:pointer;"> Tu navegador no soporta canvas </canvas> </body> </html>

Crear objetos con propiedades, métodos y eventos y animarlos en canvas

Javascript nos permite crear objetos con sus propiedades, métodos y eventos. Esos objetos posteriormente los podemos mostrar y animar en CANVAS. El resultado de este ejercicio se puede ver aquí: Crear objetos con propiedades, métodos y eventos y animarlos en canvas

El código fuente de esta animación es:

<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Crear objetos y animarlos en Canvas</title> <script> window.onload = function() // esto es un comentario en javascript // aqui creamos una función // cuando la página se cargue, ejecutarmos el siguiente código { animacion_con_canvas(); // cuando la página se cargue, ejecutarmos otra función animacion_con_canvas(); } function animacion_con_canvas() // creamos la función animacion_con_canvas { var mi_canvas = document.getElementById("canvas"); // el elemento bautizado "canvas" sera usado para crear la animaciòn var contexto = mi_canvas.getContext("2d"); // creamos el contexto para poder animar en canvas // canvas soporta animaciones en 2d y en 3d, en este ejemplo usaremos animaciones 2d var array_para_bolitas = []; // se crearan varios objetos con difefente velocidad, posición en x y posición en y // la información de cada objeto se almacenará en un array var img_bolita_roja = new Image(); // creamos un objeto del tipo imagen // Como todo objeto tiene propiedades métodos y eventos img_bolita_roja.src = "./i/canvas/k.png"; // con la propiedad src definimos la imagen a cargar. DEBE ESCRIBIRSE LA RUTA CORRECTA A LA IMAGEN img_bolita_roja.addEventListener('load', iniciar_animacion, false); // para poder mostrar la imagen, primero debe cargarse... // la imagen tienen el evento load, que se produce cuando la imagen se ha descargado en el navegador // el método EventListener permite verificar cuando la imagen se ha cargado // cuando la imagen se ha cargado ejecutaremos la función mostrar_imagen, que mostrará la imágen en el canvas // el método EventListener utiliza las variables: // (evento, función a ejecutar, indica si se desea iniciar el registro del evento) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // función para crear objetos // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * function crea_bolita(velocidad, x_pos, y_pos) // función para crear objetos // cada objeto puede tener propiedades, métodos y eventos { this.velocidad = velocidad; // cada objeto tendra una velocidad única this.x_pos = x_pos; // cada objeto tendra una posición en x única this.y_pos = y_pos; // cada objeto tendra una posición en y única } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // crea un método el objeto // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * crea_bolita.prototype.mover_bolita = function() // crea un método para la clase / objeto // este método moverá los objetos a lo largo del plano de x { if(this.x_pos<750) // si la posición del objeto es menor a 750 { this.x_pos = this.x_pos + this.velocidad; // mueve el objeto en el plano de x acorde a su velocidad } else // si la posición del objeto es mayor a 750 { this.x_pos = 0; // mueve el objeto a la posición 0 en el plano de x this.y_pos = Math.round(Math.random() * 300); // mueve el objeto en el plano de y a una posición única } contexto.drawImage(img_bolita_roja, this.x_pos, this.y_pos); // aqui utilizamo el método drawimage para mostrar a nuestra imagen dentro del canvas // el método drawimage utiliza las variables (imagen a cargar, posición en x, posición en y) // el método drawimage se puede usar indistintamente para cargar imágenes jpg, png o svg // aquí la posición en x cambiará dinámicamente // aquí la posición en y cambiará dinámicamente }; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // funcion para crear varios objetos a partir de nuestra clase // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * function crear_varias_bolitas() { for (var i = 0; i < 10; i++) // con un loop crearemos varios objetos { var x_posicion_al_azar = Math.round(Math.random() * 750); // cada objeto tendrá una posición en x al azar var y_posicion_al_azar = Math.round(Math.random() * 300); // cada objeto tendrá una posición en y al azar var velocidad_al_azar = 0.2 + Math.random() * 3; // cada objeto tendrá una velocidad al azar var bolita_creada = new crea_bolita(velocidad_al_azar, x_posicion_al_azar, y_posicion_al_azar); // se crea un nuevo objeto array_para_bolitas.push(bolita_creada); // almacenamos la información del objeto creado en un array } animar_bolitas(); // tras crear los objetos, comenzamos a animarlos con la función animar_bolitas() } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // funcion para iniciar la animación // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * function iniciar_animacion() { crear_varias_bolitas(); // ejecutamos la función crear_varias_bolitas() // con esa función creamos varios objetos } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // creamos una función para animar los objetos // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * function animar_bolitas() { contexto.fillStyle = "#ffffff"; // contexto es un objeto. Como todo objeto tiene propiedades métodos y eventos // aqui utilizamo la propiedad fillStyle para definir el color de fondo de objeto a dibujar contexto.fillRect(0, 0, 750, 300); // aqui utilizamo el método fillRect para crear un rectángulo // el método fillRect utiliza las variables (posición en x, posición en y, ancho, alto) // creamos un rectangulo para borrar el fondo // CANVAS crea animaciones cuadro por cuadro, frame by frame. // 100 años después se sigue usando el mismo método para animar. // Se dibuja un cuadro. Se dibuja otro cuadro. Se dibuja otro cuadro. Y así hasta el infinito. // El secreto está en mostrar sucesivamente esos cuadros para crear la ilusión de animación. // El método RequestAnimationFrame() intenta mostrar 60 cuadros por segundo. ¡Más rápido que el cine! // creamos un rectangulo para borrar el cuadro dibujado previamente por CANVAS for (var i = 0; i < array_para_bolitas.length; i++) // para cada una de los objetos creados... { var bolita_a_animar = array_para_bolitas[i]; // elegimos el objeto a animar desde nuestro array con objetos bolita_a_animar.mover_bolita(); // movemos el objeto con el método mover } fx_animar_bolitas = requestAnimationFrame(animar_bolitas); // invocamos la función requestAnimationFrame // requestAnimationFrame intenta ejecutar una función 60 veces por segundo // en este caso ejecutará la función animar_bolitas // el método requestAnimationFrame utiliza las variables (función a ejecutar) } } </script> </head> <body> <canvas id="canvas" width="750" height="300" style="border:3px solid #ccc;"> Tu navegador no soporta canvas </canvas> </body> </html>

Usando en canvas animaciones de celda (cell animation)

Se pueden combinar animaciones cuadro por cuadro ( frame by frame ) hechas con canvas con animaciones cuadro por cuadro ( frame by frame ) hechas con la técnica de animaciones de celda (cell animation)

100 años después de la invención del cine se sigue usando el mismo método para animar: se dibuja un cuadro, se dibuja otro cuadro, se dibuja otro cuadro... Y así hasta el infinito. El secreto está en mostrar sucesivamente esos cuadros para crear la ilusión de animación.

La técnica de animaciones de celda (cell animation) sigue el mismo principio: : se dibuja un cuadro, se dibuja otro cuadro, se dibuja otro cuadro... Y así hasta el infinito. El secreto está en mostrar sucesivamente esos cuadros para crear la ilusión de animación.

Esas animaciones cuadro por cuadro se pueden guardar en una imagen en formato jpg, png o svg. Con ayuda de sofware libre como Inkscape o Gimp podemos crear imagenes de mapas de bits (bitmaps) o imagenes svg con animaciones de celda. Entre cuadro y cuadro (frame y frame) nuestro objeto o sujeto a animar debe tener algun cambio para poder generar la ilusión de movimiento.

El resultado sería una tira (sprite: bitmap bidimensional) como esta:

El sprite debe verse como una secuencia de imagenes, que se puede dividir cuadro por cuadro / frame by frame.

Este sprite tiene 12 cuadros de 100 pixeles de ancho por 100 pixeles de alto:

Esa tira (sprite) podemos animarla usando canvas y javascript. El resultado de este ejercicio se puede ver aquí: Sprite animado en canvas

El código fuente de esta animación es:

<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Usando en canvas animaciones de celda (cell animation)</title> <script> window.onload = function() // esto es un comentario en javascript // aqui creamos una función // cuando la página se cargue, ejecutarmos el siguiente código { animacion_con_canvas(); // cuando la página se cargue, ejecutarmos otra función animacion_con_canvas(); } function animacion_con_canvas() // creamos la función animacion_con_canvas { var mi_canvas = document.getElementById("canvas"); // el elemento bautizado "canvas" sera usado para crear la animaciòn var contexto = mi_canvas.getContext("2d"); // creamos el contexto para poder animar en canvas // canvas soporta animaciones en 2d y en 3d, en este ejemplo usaremos animaciones 2d var img_sprite = new Image(); // creamos un objeto del tipo imagen // Como todo objeto tiene propiedades métodos y eventos img_sprite.src ="./i/canvas/epn_sprite.png"; // con la propiedad src definimos la imagen a cargar. DEBE ESCRIBIRSE LA RUTA CORRECTA A LA IMAGEN // en este caso cargamos el sprite con la animación cuadro por cuadro img_sprite.addEventListener('load', mostrar_imagen, false); // para poder mostrar la imagen, primero debe cargarse... // la imagen tienen el evento load, que se produce cuando la imagen se ha descargado en el navegador // el método EventListener permite verificar cuando la imagen se ha cargado // cuando la imagen se ha cargado ejecutaremos la función mostrar_imagen, que mostrará la imágen en el canvas // el método EventListener utiliza las variables (evento, función a ejecutar, indica si se desea iniciar el registro del evento) var cuadro_del_sprite = 0; // esta variable la usaremos para registrar que cuadro del sprite estamos usando // el sprite tiene una secuencia de imagenes que darán la ilusión de movimiento // el sprite puede dividirse en cuadros / frames // el sprite lo dividimos de izquierda a derecha. el primer cuadro se localizará del lado izquierdo // el último cuadro estará en el extremo derecho del sprite // cada cuadro / frame indica una parte de la secuencia de imagenes que darán la ilusión de movimiento // iniciaremos la animación con el primer cuadro / frame var cuadros_por_segundo = 0; // esta variable la usaremos para determinar cuantos cuadros / frames del sprite mostaremos por segundo var xpos = 0; // posicion inicial de nuesto objeto a animar dentro del canvas // ademas de animar el sprite, animaremos el sprite dentro del canvas var velocidad = 0.16; // ademas de animar el sprite, animaremos el sprite dentro del canvas // cuantos pixeles en 0.016 segundos avanzara nuestro objeto a animar // IMPORTANTE: requestAnimationFrame() se ejecuta 60 veces por segundo // aqui el objeto se animará 10 pixeles por segundo // 0.16 = 10 pixeles por segundo / 60 veces por segundo que se ejecuta requestAnimationFrame() // si queremos que nuesto objeto se mueva más rápido o lento, solo tenemos que modificar la velocidad function mostrar_imagen() // creamos la función mostrar_imagen para mostrar la imagen en el canvas // esta función se ejecuta cuando la imagen se ha cargado { fx_animar_imagen = requestAnimationFrame(mostrar_imagen); // invocamos la función requestAnimationFrame // requestAnimationFrame intenta ejecutar una función 60 veces por segundo // en este caso ejecutará la función animar_imagen // el método requestAnimationFrame utiliza las variables (función a ejecutar) contexto.fillStyle = "#ffffff"; // contexto es un objeto. Como todo objeto tiene propiedades métodos y eventos // aqui utilizamo la propiedad fillStyle para definir el color de fondo de objeto a dibujar contexto.fillRect(0, 0, 1000, 300); // aqui utilizamo el método fillRect para crear un rectángulo // el método fillRect utiliza las variables (posición en x, posición en y, ancho, alto) // creamos un rectangulo para borrar el fondo // CANVAS crea animaciones cuadro por cuadro, frame by frame. // 100 años después se sigue usando el mismo método para animar. // Se dibuja un cuadro. Se dibuja otro cuadro. Se dibuja otro cuadro. Y así hasta el infinito. // El secreto está en mostrar sucesivamente esos cuadros para crear la ilusión de animación. // El método RequestAnimationFrame() intenta mostrar 60 cuadros por segundo. ¡Más rápido que el cine! // creamos un rectangulo para borrar el cuadro dibujado previamente por CANVAS contexto.drawImage(img_sprite, 100*cuadro_del_sprite, 0,100,100,xpos,0,100,100); // esta linea de código hace la magia de animar el sprite // aqui utilizamo el método drawimage para mostrar a nuestra imagen dentro del canvas // con los parametros adecuados podemos mostrar solo una parte del sprite // con los parámetros adecuados podemos mostrar un cuadro / frame de nuestro sprite // el método drawimage utiliza las variables: //a) imagen a cargar: img_sprite //b) posición en x dentro del sprite: 100*cuadro_del_sprite // (cada cuadro /frame tiene un ancho de 100 pixeles) // cuadro_del_sprite es una variable que almacena que cuadro /frame de nuestro sprite estamos usando //c) posición en y dentro del sprite: 0 //(nuestro sprite solo tiene una fila de cuadros / frames) //d) tamaño en x dentro del sprite: 100 //(el sprite lo podemos recortar, aque definimos el tamaño del recorte: 100 pixeles de ancho) //e) tamaño en y dentro del sprite: 100 // (el sprite lo podemos recortar, aque definimos el tamaño del recorte: 100 pixeles de alto) //f) posición en x dentro del canvas: xpos // adicionalmente animaremos el sprite dentro del canvas, // xpos almacena dinámicamente la posición en x dentro del canvas //g) posición en y dentro del canvas: 0 // la posicion en y de nuestro sprite dentro del canvas //h) tamaño en x dentro del canvas: 100 (en el canvas el sprite tendrá un tamaño de 100 pixeles de ancho) //i) tamaño en y dentro del canvas: 100 (en el canvas el sprite tendrá un tamaño de 100 pixeles de alto) // el método drawimage se puede usar indistintamente para cargar imágenes jpg, png o svg xpos = xpos + velocidad; // aumentamos el valor de xpos con el valor de velocidad cuadros_por_segundo++; // esta variable la usaremos para determinar cuantos cuadros / frames del sprite mostaremos por segundo // cada que se ejecute requestAnimationFrame aumentará en 1 el valor de cuadros_por_segundo if(cuadros_por_segundo%3==0) // en este ejemplo nuestro sprite sólo tiene 12 cuadros / frames // requestAnimationFrame intenta ejecutar una función 60 veces por segundo // debemos reducir la velocidad de la animación frame by fram / cuadro por cuadro de nuestro sprite // cuadros_por_segundo la usaremos para determinar cuantos cuadros / frames del sprite mostaremos por segundo // si cuadro cuadros_por_segundo es múltiplo de 3, mostraremos un cuadro / frame diferente del sprite // en un segundo mostraremos 20 cuadros / frames de nuestro sprite // sin esta línea de código en un segundo mostraríamos 60 cuadros / frames de nuestro sprite... { cuadro_del_sprite++; // esta variable la usaremos para registrar que cuadro / frame del sprite estamos usando // si cuadro cuadros_por_segundo es múltiplo de 3, mostraremos un cuadro / frame diferente del sprite if (cuadro_del_sprite >11) // este sprite tiene 12 cuadros / frames // cuando llegue al último frame / cuadro comenzaremos a mostrar nuevamente el primer frame { cuadro_del_sprite = 0; // reniniciamos el sprite // mostramos el primer cuadro / frame del sprite } } } } </script> </head> <body> <canvas id="canvas" width="1000" height="300" style="border:3px solid #ccc;"> Tu navegador no soporta canvas </canvas> </body> </html>

Sitios de interés

Mozilla Developer Network Sitio para aprender html5, javascript, css

W3Schools Sitio para aprender html5, javascript, css, php, sql

CodeAcademy Sitio para aprender html5, javascript, css, php, sql

BrowserQuest

Asteroids

El juego de google para el Halloween de 2016

Keepout

Hexgl

Contre Jour


Comenta y opina este texto     Lee mi libro de visitas
© 1997-2017 Alain García Gómez
albegago@hotmail.com
@feesgo
El vínculo a este documento es:

Puedes apoyar a este sitio invitándome a comer...

Este sitio utiliza cookies propias y de terceros para mejorar sus servicios. Si continua navegando, entendemos que acepta su uso. Política de Privacidad