Si bien este artículo no posee demasiada profundidad técnica, es recomendable tener  los conceptos básicos del canvas asimilados. Un buen comienzo se puede encontrar en la documentación de Mozilla (MDN).

Introducción

Con la concepción de lo que hoy en día llamamos HTML5, los browsers han ganado muchas herramientas para proveer una mejor experiencia de usuario.

El canvas, sin duda alguna, es la característica más marketinera que propone este “estándar”, permitiendo generar visualizaciones complejas de manera nativa. Existen en la web algunos ejemplos espectaculares que demuestran el gran potencial que tiene esta característica, tanto en dos dimensiones como en tres.

A diferencia de otros modos de render disponibles en el browser (DOM y SVG) el canvas no dispone de una persistencia de estado más allá del aspecto visual que presenta, lo cual implica la ausencia absoluta de referencias de que y donde dibujamos.

Librerías como three.js, heatmap.js, d3.js, entre otras, brindan grandes ejemplos de lo que se puede lograr dentro de un browser, explotando tanto las características 2d como 3d (utilizando WebGL) de este elemento para proveer soluciones a distintas problemáticas.

Soporte

El elemento <canvas> esta disponible en la gran mayoría de los browsers actuales:

  • Firefox desde la versión 1.5 (parcial)
  • Safari desde la versión 2
  • Opera desde la versión 9
  • Chrome desde la versión 4
  • Internet Explorer desde la versión 9

Más información sobre el soporte en los distintos browsers se puede encontrar en varios sitios de la web, por ejemplo caniuse.com.

Alternativas

Si bien es totalmente contextual el requerimiento, el uso de canvas se puede reemplazar por animaciones CSS3, SVG o inclusive las ya clásicas animaciones DOM (scriptaculous, jQuery.fx, etc). Obviamente, cada una de estas soluciones tiene sus casos de uso recomendados y los no recomendados (así como su grado de dificultad), pero por supuesto, en ésta ocasión les hablaremos puntualmente de Canvas :).

Animaciones básicas

En una definición simple, podríamos decir que una animación, es ni más ni menos que un conjunto de cuadros (imágenes) que se suceden con un intervalo dado generando la impresión de movimiento.

Esta idea no cambia cuando hablamos de animación utilizando canvas, idea que aplicaremos en un pequeño ejemplo, en el cual desplazaremos un cuadrado por el canvas.

Para este primer ejemplo, primeramente vamos a generar nuestro HTML, que contendrá el canvas sobre el cual dibujaremos:

<canvas id="canvas" width="100" height="100"></canvas>

Para hacerlo más visible a nuestros queridos ojos con respecto al background, vamos a darle un borde y margen:

canvas { border: solid 1px #ccc; margin: 20px; }

El corazón de la animación está dado por el proceso de generar el intervalo entre las imágenes, el cual resolveremos inicialmente (y a fines de simplificar) con el uso de la función setInterval. De cualquier manera hablaremos sobre el framerate en breve.

[tipexperto titulo = “Nota”]Idealmente el renderizado debería darse siempre a la mayor velocidad posible (~60fps utilizando el método requestAnimationFrame), independientemente de los requerimientos/velocidad de la animación, sus objetos y/o sucesos.[/tipexperto]

En este primer ejemplo vamos a generarlo en 24 frames por segundo (fps de ahora en más), que resulta lo suficientemente fluido a la vista y no requiere mayor complejidad.

// Nuestro código de inicialización irá aquí
setInterval(function() {
    // ... la magia sucede aqui
}, 1000 / 24);

Luego, para dar vida a esta grandiosa animación, completamos la lógica:

// Nuestras variables
var canvas, ctx, x, y;

// Obtenemos una referencia al canvas

canvas = document.getElementById('canvas');

// Y a su contexto 2d
ctx = canvas.getContext('2d');

// Generamos las coordenadas iniciales
x = 0;
y = 0;

// Los frames seran renderizados por este intervalo

// aproximadamente a 24 frames por segundo (fps)
setInterval(function() {
   // Limpiamos el canvas, eliminando el contenido
   // desde el punto (0, 0) al punto (100, 100)
   ctx.clearRect(0, 0, 100, 100);

   // Generamos nuevas coordenadas
   // Que basicamente representan un desplazamiento lineal
   x = x >= 100 ? 0 : x + 1;
   y = y >= 100 ? 0 : y + 1;

   // Y dibujamos nuestra figura
   ctx.fillRect(x, y, 50, 50);
}, 1000 / 24);

Este ejemplo se puede encontrar funcional en este fiddle.

Utilizando imágenes

Sprite

Por suerte para nosotros, canvas provee métodos para trabajar con imágenes, lo cual además de generar hermosos backgrounds e imágenes estáticas nos permite utilizar “sprites”.

En este caso (bastante general por cierto), utilizaremos un sprite que contiene las gráficas de distintos estados de movimiento de un personaje (bastante elegante por cierto).

Para dibujar las imágenes utilizaremos el método drawImage, cuya firma acepta hasta 9 (¡nueve!) argumentos. Más información sobre este horrible método se puede encontrar en el tutorial de Mozilla previamente mencionado.

<canvas id="canvas" width="100" height="100"></canvas>

El background de este ejemplo, llega a ustedes gracias a @leaverou y su útil artículo/catálogo “Checkerboard, striped & other background patterns with CSS3 gradients“.

canvas {
    background-color: #eee;

    background-image: -webkit-linear-gradient(45deg, black 25%, 
transparent 25%, transparent 75%, black 75%, black), 
-webkit-linear-gradient(45deg, black 25%, transparent 25%, 
transparent 75%, black 75%, black);

    background-image: -moz-linear-gradient(45deg, black 25%, 
transparent 25%, transparent 75%, black 75%, black), 
-moz-linear-gradient(45deg, black 25%, transparent 25%, 
transparent 75%, black 75%, black);
    background-image: linear-gradient(45deg, black 25%, transparent 25%, 
transparent 75%, black 75%, black), linear-gradient(45deg, black 25%, 
transparent 25%, transparent 75%, black 75%, black);

    background-size:60px 60px;
    background-position:0 0, 30px 30px
}

El código, nuevamente es bastante sencillo, siendo básicamente una función que es llamada en cada iteración, calculando la posición y frame a dibujar:

// Nuestras variables
var canvas, ctx, img, x, y, step, direction;

canvas = document.getElementById('canvas');
ctx = canvas.getContext('2d');
img = document.getElementById('img');

// La posición x inicial, variara con cada paso
x = 0;
// La posición y inicial, quedará estática
y = 25;

// Numerador de paso, lo usaremos para saber que frame dibujar
step = 0;

// Direccion, 1 derecha, -1 izquierda
direction = 1;

setInterval(function() {
    // Borramos lo dibujado
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    // Dibujamos el frame adecuado en la posicion correspondiente
    ctx.drawImage(
        // Imagen
        img,
        // Source x
        (step++ % 4) * 32, // Avance sobre el eje x
        // Source y
        [52, 0, 104][direction + 1], // Selecciona el frame adecuado
        // Source width
        32,
        // Source height
        52,
        // Dest x
        x,
        // Dest y
        y,
        // Dest width
        32,
        // Dest height
        52
    );

    // Avance, indistinto de la direccion
    x += 5 * direction;

    // Si toca un limite, cambiamos la dirección
    if (x >= canvas.width - 32 || x <= 0) {
        direction = -direction;
    }
}, 1000 / 12); // Aproximadamente 12 frames por segundo

Este ejemplo se puede encontrar funcional en este fiddle.

En éste artículo conocimos acerca del soporte y otras alternativas a Canvas. Profundizamos un poco en el código con la manipulación de imágenes básicas y estáticas, la próxima semana veremos más acerca de la interactividad, framerate, consideraciones sobre performance, recomendaciones de lecturas y sitios para aprender más de Canvas.