Universitat Oberta de Catalunya

Introducción a Canvas de HTML5

Introducción

Con la aparición del nuevo estándar HTML5 la web ha sufrido una revolución y ahora es posible estructurar los sitios web con una semántica más detallada. Además estos aspectos de estructura y semántica tambien se abre un gran abanico de posibilidades para trabajar con vídeo, audio, interactividad y animación de gráficos. Gracias a todos estos avances, la web ya no es sólo la acumulación de metatexto, imágenes y vídeo. Ahora se pueden desarrollar desde espacios web 100% interactivos sin el uso de plugins, hasta videojuegos y documentales interactivos.

El motivo de este artículo es la etiqueta canvas que es la responsable que permite abrir una ventana de gráficos en tu página web.

<canvas></canvas>

Se puede entender canvas como un lienzo en el que un artista puede pintar sus obras: canvas es el tapiz y el código el pincel.

Con esta etiqueta tienes la posibilidad de crear un lienzo en tu página web en la que puedes introducir elementos, animarlos y que interaccionen con el usuario. Se puede entender canvas como un lienzo en el que un artista puede pintar sus obras: canvas es el tapiz y el código el pincel. Esta etiqueta no deja de ser una matriz de píxeles en que se muestran las imágenes y colores que el desarrollador ha programado. Este lienzo es totalmente adaptable y manipulable a gusto del desarrollador y con toda la API que lleva consigo es posible añadir todos los aspectos y funciones que puedas imaginar.

Desarrollo

Para empezar, es necesario introducir la etiqueta canvas en el body de nuestro sitio web. En el siguiente ejemplo se muestra la estructura básica del código necesario:

<!DOCTYPE html>
<html lang=”es”>
<head>
<meta charset="utf-8">
<script type="text/javascript" src="js/canvas.js"></script>
</head>
<body>
<canvas id=”canvas”>
<p>Tu navegador no soporta canvas. Actualizalo para que esta funcionalidad esté disponible</p>
</canvas>
</body>
</html>

En la plantilla de este tutorial se puede observar que entre las etiquetas de canvas se ha introducido un texto explicativo. Esto es opcional pero es un buen recurso, ya que este texto sólo será visible en caso que el navegador que visualice la página web no sea capaz de interpretar esta etiqueta. Además, he añadido una etiqueta script en el head para escribir el código que será responsable de añadir funcionalidad a canvas.

<script type="text/javascript" src="js/canvas.js"></script>

Para esto es necesario crear un archivo javascript y situarlo en la carpeta /js de la raíz de tu sitio web. Acto seguido, para acceder a las funcionalidades de canvas es necesario tener un conocimiento básico de javascript. El primer paso es acceder al DOM para darle formato a nuestro canvas. Para ello crearemos dos variables:

var canvas = null;
var ctx = null;

y las inicializamos de la siguiente manera:

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

Con la variable canvas accedemos a la etiqueta <canvas> usando el método getElementById() y con la variable ctx añadimos el contexto de dos dimensiones a nuestro lienzo. En este punto también es posible añadir un contexto en tres dimensiones pero para este contexto se necesitan librerías javascript como puede ser three.js  o tecnología webGL. En este tutorial introductorio me centro en el contexto en dos dimensiones ya que se trata de ir avanzando poco a poco y poder entender bien el código.

A continuación, se definirán las dimensiones de altura y ancho del tapiz y le añadiremos un color de fondo.

canvas.width = 500;
canvas.height = 250;
canvas.style.backgroundColor = '#FF5050';

Una vez el canvas ya tiene todas sus propiedades de contexto, ancho, alto y color definidos es momento de darle movimiento. Para esto se necesita que el canvas se actualice como mínimo 25 veces por segundo, ya que es el mínimo que necesita el ojo humano para crear la ilusión de movimiento. Para conseguir que nuestro canvas se pinte tantas veces por minuto, la API de canvas tiene el método requestAnimationFrame(). Para ellos, primero copiamos el siguiente código al final del documento:

window.requestAnimationFrame=(function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function(callback){window.setTimeout(callback,17);};
})();

De esta manera, permite al canvas actualizarse tantas veces por segundo como nuestro navegador (Chrome, Mozilla, IE, etc.) sea capaz de hacerlo. Por otro lado, es necesario crear una función que yo llamaré movimiento() en la que en su interior esté el método requestAnimationFrame que reciba como parámetro la misma función donde está situado convirtiéndola en una función recursiva indirecta:

function movimiento(){
requestAnimationFrame(movimiento);
}

El siguiente paso es necesario crear una función que yo la llamaré dibujar(ctx) y la ejecutaré desde dentro de la función movimiento(), y como ya has podido ver, necesitará recibir como parámetro el contexto del canvas. En su interior usaremos los métodos de la API de canvas para poder dibujar. Primero, usaremos el método clearRect() para borrar todo el contenido del canvas cada vez que se pinte un frame en pantalla:

function dibujar(ctx){
ctx.clearRect( 0, 0, canvas.width, canvas.height);
}

A continuación dibujaremos un cuadrado en pantalla de color azul. Primero de todo usaremos el método fillStyle para concretar el color azul y después usaremos el método fillRect con sus dimensiones incluidas

function dibujar(ctx){
ctx.clearRect( 0, 0, canvas.width, canvas.height);
ctx.fillStyle = "#61A8FF";
ctx.fillRect(20, 150, 50, 50);
}

El método fillRect dibuja una figura de cuatro lados. En este caso, se empieza a dibujar en la coordenada X del canvas de 20 píxeles y la coordenada Y de 150 píxeles; con una anchura de 50 píxeles y un alto de 50 píxeles.

Un canvas rojo con un cuadrado azul dibujado
Muestra gráfica del resultado del código de este recurso

Hasta este punto hemos conseguido definir un canvas en una página web, que se actualice varias veces por segundo y dibujar un cuadrado. Ahora le daremos movimiento a este objeto; para ello crearemos una nueva función que yo llamaré interaction() y la ejecutaremos desde la función movimiento() de la siguiente manera:

function movimiento(){
requestAnimationFrame(movimiento);
interaction();
dibujar(ctx);
}

Para el siguiente paso es necesario crear una variable global para poder mover el cuadrado por la pantalla:

var x = 20;

En la función interaction() aplicaremos un incremento de la variable X de la siguiente forma:

function interaction(){
x++;
}

Así, cada ciclo en que se pinte el canvas la variable X aumentará un valor entero. Entonces sólo queda indicar el valor de la variable X en el método para dibujar el rectángulo:

ctx.fillRect(x, 150, 50, 50);

Por último, se podría conseguir que al pulsar una tecla del teclado se active el movimiento del cuadrado. Para ello primero crearemos una variable donde se almacenará el valor numérico de la tecla pulsada y a continuación crearemos otra variable de tipo arreglo para almacenar el valor de la última tecla pulsada.

var ultimaTecla = null;
var tecla = [];

Las teclas que usaremos para mover el cuadrado serán las flechas del teclado. Para ello crearemos cuatro variables con sus valores correspondientes:

var LEFT = 37;
var UP = 38;
var RIGHT = 39;
var DOWN = 40;

En javascript cada tecla del teclado tiene asociado un valor numérico y las variables que dan las coordenadas del cuadrado en nuestro canvas:

var x = 150;
var y = 150;

Después añadiremos un escuchador de eventos que detecte las teclas pulsadas del teclado.

document.addEventListener('keydown',function(evt){
ultimaTelca=evt.keyCode;
tecla[evt.keyCode]=true;
},false);

Este escuchador de eventos está esperando el evento ‘keydown’ para almacenar el valor de la tecla pulsada en la variable ultimaTecla.

Por último, debemos modificar la función interaction() y añadir los siguientes condicionales:

function interaction(){
if(tecla[UP])
y-=10;
if(tecla[RIGHT])
x+=10;
if(tecla[DOWN])
y+=10;
if(tecla[LEFT])
x-=10;
}

El resultado de este código con condicionales es que al pulsar las teclas de las flechas del teclado se incrementen o decrementen los valores de las variables X y Y.

Por ese motivo, en el método para dibujar nuestro cuadrado se debe añadir las variables X y Y:

ctx.fillRect(x, y, 50, 50);

Aquí termina este sencillo tutorial introductorio de cómo iniciarse en el uso de canvas de HTML5. Éste es sólo un pequeño paso y demostración de lo que se puede hacer con canvas. Esta tecnología, con la llegada del nuevo estándar HTML5 tiene un gran potencial y merece la pena detenerse un momento para descubrir gran parte de sus posibilidades.

Resumen

Como habrás visto, los métodos y técnicas de programación para canvas son muy sencillas. Con un poco de conocimiento y visión se pueden llegar a crear grandes desarrollos interactivos como videojuegos y películas interactivas.

A continuación dejaré todo el código del archivo canvas.js con el código correspondiente de este recurso para que su comprensión sea más fácil:

//Variables
var canvas, contexto;
var ultimaTecla = null;
var tecla = [];
var LEFT = 37;
var UP = 38;
var RIGHT = 39;
var DOWN = 40;
var x = 150
var y = 150;
    
canvas = document.getElementById('canvas');
contexto = canvas.getContext('2d');
canvas.width = '800';
canvas.height = '400';
canvas.style.backgroundColor = '#FF5050';

//Ejecutamos la interacción
movimiento();

function movimiento(){
    requestAnimationFrame(movimiento);
    interaction();
    dibujar(contexto);
}

function interaction(){
//Interactividad en función de la tecla pulsada
    if(tecla[UP])
            y-=10;
        if(tecla[RIGHT])
            x+=10;
        if(tecla[DOWN])
            y+=10;
        if(tecla[LEFT])
            x-=10;
}

function dibujar(contexto){
	//Borramos el canvas cada vez que se actualiza
 	contexto.clearRect( 0, 0, canvas.width, canvas.height);

	//dibujamos el cuadrado azul en el canvas
    contexto.fillStyle = "#61A8FF";
    contexto.fillRect(x, y, 50, 50);
}

//Escuchador de eventos
document.addEventListener('keydown',function(evt){
    ultimaTecla=evt.keyCode;
    tecla[evt.keyCode]=true;
    },false);

window.requestAnimationFrame=(function(){
    return window.requestAnimationFrame || 
    window.webkitRequestAnimationFrame || 
    window.mozRequestAnimationFrame || 
    function(callback){window.setTimeout(callback,17);};
})();

Cita recomendada: SUELVES, Sergi. Introducción a Canvas de HTML 5. Mosaic [en línea], abril 2915, no. 126. ISSN: 1696-3296. DOI: https://doi.org/10.7238/m.n126.1507.

2 comentarios

Deja un comentario

  1. He probado el código y no me funciona, he visto varios fallos: ultimatelca en vez de ultimatecla era uno, otro es culpa del copia-pega que cambiaba algunas comillas del HTML por otras que no sirve para el código, y finalmente no llegaba a iniciarse porque daba error de que canvas era null.

    Para que canvas se creara antes de usarlo he agregado al final del fichero canvas.js la línea: window.addEventListener(“load”, iniciar, false);

    Y he encerrado la parte de iniciación del canvas en la función iniciar():
    function iniciar(){

    canvas = document.getElementById(‘canvas’);
    contexto = canvas.getContext(‘2d’);
    canvas.width = ‘800’;
    canvas.height = ‘400’;
    canvas.style.backgroundColor = ‘#FF5050’;

    //Ejecutamos la interacción
    movimiento();
    }

    Con esto conseguí que empezara a funcionar, pero sólo hace caso a la primera vez que voy a un lado o arriba o abajo, pero deja de hacerme caso tras estas teclas y se queda sin funcionar.
    Para que el cuadrado se quedara en la pantalla para no perderlo de vista añadí a la función interacción() las líneas:
    if(x < 0) x = 10;
    if(y canvas.width) x = canvas.width-10;
    if(y > canvas.height) y = canvas.height-10;

    Y finalmente vi que para que dejara pulsar más teclas había que vaciar la variable tecla añadiendo al final de interaccion() la línea:
    tecla = [];

    Por fin trabajó. Me queda duda si no hay que eliminar de alguna forma la memoria ocupada por la variable tecla antes de crear una nueva variable tecla tal vez en otro lado de la memoria del sistema.

    Total, gracias por el artículo pero tiene muchos fallos que deberían haber sido pulidos para no desesperar a los novatos totales (yo tengo conocimientos de programación en otros lenguajes y por ello no me he asustado demasiado).

    Saludos.

    Respon
  2. No me acuerdo si lo dije, todavía no sale mi comentario, es que en el HTML comienza por <DOCTYPE en vez de por <!DOCTYPE, falta el signo de admiración al principio.

    Respon

Responde Guillermo