
Como prometí anteriormente, en el post de hoy voy a hacer una introducción al elemento canvas de HTML5 profundizando un poco en sus características, sus virtudes y sus defectos.
El elemento canvas puede definirse como un entorno para crear imágenes dinámicas. El propio elemento es relativamente simple. Lo único que hay que especificar al usarlo son sus dimensiones:
<canvas id="entorno_canvas" width="360" height="240">;
</canvas>
Cualquier cosa que escribamos entre la apertura y cierre de la etiqueta canvas solamente será interpretado por navegadores que no soportan aún la nueva etiqueta.
<canvas id="entorno_canvas" width="360" height="240">
<p>Tu navegador no soporta canvas: Aquí deberías de ver una imagen :</p>
<img src="html5_logo.png" alt="HTML5" />
</canvas>
En el ejemplo anterior, la imagen solo sería visible por aquellos navegadores que aún no soporten canvas
¿Cómo se usa?
Cuando trabajamos con canvas, realmente toda la magia la haremos en JavaScript. Primero debemos referenciar el elemento canvas y adquirir su contexto (API). Por el momento el único contexto disponible es el contexto bidimensional. Recomiendo usar firebug o similares a la hora de aprender a usar la API para poder ver los cambios en vivo y avanzar con mayor velocidad:
var canvas = document.getElementById('entorno_canvas');
var context = canvas.getContext('2d');
Una vez adquirimos el contexto, podemos empezar a dibujar en la superficie del canvas usando la API a tal efecto documentada en http://bit.ly/l1BMyi . La API bidimensional ofrece muchas de las herramientas que podemos encontrar en cualquier aplicación de diseño gráfico como Adobe Illustrator o Inkscape: trazos, rellenos, gradientes, sombras, formas y curvas Bézier. Claro está deberemos especificar cada acción con ellas usando JavaScript.
Dibujar con JavaScript
Puede parecerte que dibujar usando código JavaScript es algo tedioso y pesado, pero lo cierto es que cuando le pillas el punto puede ser muy divertido. De momento, vamos a especificar el color del trazo:
context.strokeStyle = '#8f9814';
Cualquier cosa que dibujemos tendrá un contorno de color verde. Para visualizar este ejemplo, vamos a dibujar un rectángulo:
context.strokeRect (20, 30, 100, 50);
La sintaxis del método strokeRect es como sigue strokeRect (izquierda, arriba, ancho, largo). Por lo tanto, en el ejemplo anterior, hemos dibujado un rectángulo posicionado a 20 pixels del margen izquierdo y 30 del derecho con un tamaño de 100×50 pixels.

Si por ejemplo queremos dibujar un rectángulo relleno con color, deberemos de especificar el color del relleno:
context.fillStyle = '#ff8f43';
Y dibujar un rectángulo con relleno:
context.fillRect(20, 30, 100, 50);

¿Y si quiero hacer un rectángulo con trazo y relleno?. Pues generamos uno dentro del otro y listo:
context.fillRect(20, 30, 100, 50);
context.strokeRect(19, 29, 101, 51);

La API 2D tiene muchísimos métodos para trabajar con ella, échale un ojo al link anterior para ver sus especificaciones. En teoría, podemos crear cualquier imagen que pudiéramos dibujar en un programa de edición de gráficos vectoriales. Hacerlo en la práctica puede ser (y es) una tarea titánica a realizar con archivos JavaScript interminables. Obviamente, la etiqueta canvas no se ha creado para eso.
¿Para que sirve canvas?
El potencial de canvas reside en su habilidad para actualizar su contenido en tiempo real. Si usamos esa habilidad para responder a eventos de usuario, podemos crear herramientas y juegos que anteriormente a la nueva especificación hubiesen requerido de un plugin externo como Flash.
Se pueden hacer cosas increibles con canvas, una de las aplicaciones que más me han impresionado es Skywritter (Bespin) que después se integraría en Ace aunque éste último usa el DOM para dibujar el texto en lugar de canvas. Podemos ver unas screenshots de Skywritter (Bespin) en acción.


Como puedes comprobar, el potencial de canvas es enorme y no tiene nada que envidiar a plugins o frameworks JavaScript. Skywritter (Bespin) es muy potente e impresionante pero no es solo eso, es el mejor ejemplo de que no hacer con canvas.
¿Y eso por qué? te estarás preguntando. Pues porque el editor de Skywritter (Bespin) maneja el texto con el elemento canvas solo que no es texto, son una serie de formas que aparentan ser texto. Todo documento en la Web debería de poder ser descrito con un objeto DOM. El contenido dentro de canvas no puede ser representado como nodos de un objeto DOM y debemos huir de ese tipo de prácticas.
Algunos dispositivos como los lectores de pantallas y otro tipo de tecnología que provee de accesibilidad a personas discapacitadas necesitan tener acceso al DOM para que el documento tenga sentido para ellos. Es decir, sin DOM no hay accesibilidad. La falta de accesibilidad de canvas puede definirse como una gran cagada de HTML5. Si el contenido de la web (por muy chulo que esté) no puede ser accedido por cualquier tipo de dispositivo facilitando así la accesibilidad, canvas estará cometiendo los mismos errores que Flash antes que él. Aunque por fortuna, ya hay gente trabajando en una solución.
Y menos aún si lo comparamos con lo que el equipo de Ace ha conseguido desde que Skywritter se mezclara con él utilizando el DOM para dibujar el texto y por lo tanto haciéndolo accesible. Si dispones de cuenta en Github puedes probar un editor completo “en la nube“ desarrollado con JavaScript en Cloud 9 IDE, a continuación puedes ver una captura de la edición de uno de mis proyectos:

Un uso inteligente de canvas
Una posible norma a la hora de usar canvas mientras se solucionan sus problemas de accesibilidad es la misma que aplicamos cuando utilizamos JavaScript como una mejora de nuestro sitio web pero mantenemos la accesibilidad para navegadores que no soportan JavaScript como son los lectores de pantalla. Supongamos que queremos mostrar los datos en una tabla, podemos usar la API de Google Chart para generar gráficos a partir de los datos de esta tabla, pero los datos representados dentro del canvas deben de seguir siendo accesibles en la tabla existente.
Existe un plugin para jQuery que hace precisamente eso, puedes encontrarlo en el siguiente link http://bit.ly/leDerk. Existen otras alternativas a canvas que si pueden ser accesibles, el formato SVG está basado en XML y el XML es accesible por dichos dispositivos. Teóricamente se podría hacer lo mismo con un SVG que lo que se puede hacer con canvas pero parece ser que los desarrolladores no le han puesto demasiado empeño.
Canvas fue creado por Apple que lo añadió a Safari, el resto de fabricantes sencillamente lo copiaron, y eso no tiene por que ser malo si se consigue solucionar los problemas que el nuevo elemento presenta. Hay que recordar que los estándares siempre vienen de los fabricantes y después surgen las especificaciones y la estandarización. Por ejemplo, Microsoft añadió en IE5 al final de los 90 el objeto XMLHttpRequest y ahora está siendo estandarizado por la W3C.
Conclusión
El nuevo elemento canvas nos ofrece una potencia desconocida hasta el momento en el desarrollo de páginas web, algunos frameworks JavaScript como ExtJS4 ya incorporan este elemento en sus rutinas de renderizado HTML. Ya hemos visto cuales son los problemas que se le imputan al elemento debido a su falta de accesibilidad, como con toda herramienta, debemos hacer un uso inteligente de ella e intentar no abusar y ser diligentes o convertiremos canvas en un nuevo elemento oscuro, inaccesible e insolidario como ciertos plugins existentes.
Aunque he de reconocer que lo que se puede hacer con él es una auténtica pasada. Esperemos que sus problemas se solucionen pronto puesto que es mucho lo que este nuevo elemento puede aportar al desarrollo web.
Nota: Gracias a macdav que con este comentario ha destapado un gazapo en el artículo original que ha podido ser corregido.
En Genbeta Dev | Introducción a HTML5
Comentarios
Artículo muy interesante.
Sobre Canvas vs SVG, había un post interesante del equipo de IE explicando cuáles pensaban ellos que debían ser las pautas a la hora de optar por una tecnología u otra: http://blogs.msdn.com/b/ie/archive/2011/04/22/thoughts-on-when-to-use-canvas-and-svg.aspx
En general, la regla parece ser intentar usar SVG por lo que comentas del árbol DOM y la accesibilidad, aunque en gráficos que necesitan "tiempo real" como videojuegos y similares, Canvas es la opción en la mayoría de escenarios.
Para los gráficos de tarta y similares, SVG es mejor porque, entre otras ventajas, ser vectorial le permite adaptar el tamaño sin perder ninguna clase de definición. Y eso, con la variedad de dispositivos y tamaños de pantalla que manejamos hoy en día, es una ventaja clave.
Gracias!
Queremos más, más :-P
Personalmente, aunque no soy un desarrollador web, la filosofía de SVG me parece mucho mejor, dado que permite un mayor control sobre los elementos además que puedes integrar o modificar imagenes generadas en otros entornos.
Sin duda el uso de Canvas es la parte que, al menos a mí, se me hace más dificultosa pero a la vez fascinante de HTML5.
Con esto ya podríamos comenzar a hablar de programación y no solo de marcaje sin duda. Mi único temor es que todo esto vaya encaminado a ser un monstruo incontrolable que cada que tarde a temprano se termine saliendo de las manos y volvamos a una web hecha un galimatías.
Estupendo post, ya tenia yo ganas de empezar a ver como se maneja canvas.
canvas es muy superior a nada que exista actualmente bien sea en forma de plugin o con frameworks JavaScript.
Rotundamente falso.
Canvas es bastante inferior a lo que se puede hacer ahora mismo con Flash en cuanto a funcionalidad (capas, transformaciones, filtros, 3d). Podríamos decir que es similar a lo que se podía hacer con Flash hace muchos años.
Y eso en funcionalidad, de benchmarking ni hablamos (http://www.themaninblue.com/writing/perspective/2010/03/22/).
Saludos mserranom.
El texto dice "Como puedes comprobar, el potencial de canvas es muy superior a nada que exista actualmente bien sea en forma de plugin o con frameworks JavaScript.".
Me gusta que no se saquen las cosas de contexto y en esa frase hablo del potencial de Canvas para hacer cosas como Cloud 9 IDE. Dudo mucho que se pueda hacer una aplicación como esa con Flash.
Muchísimas gracias por poner los Benchmarks pero... ¿los has pasado tu mismo o solo has mirado la gráfica?.
Estos son los resultados que me da a mi:
Google Chrome 12.0.742.91 bajo Gentoo Linux
Benchmark HTML: Entre 52 y 62 FPS sostenido
Benchmark Canvas: Entre 86 y 92 FPS sostenido
Benchmark SVG: Entre 126 y 132 FPS sostenido
Benchmark Flash 10: Entre 46 y 50 FPS sostenido
Mozilla Firefox 3.6.17 bajo Gentoo Linux
Benchmark HTML: Entre 6 y 10 FPS sostenido
Benchmark Canvas: Entre 15 y 16 FPS sostenido
Benchmark SVG: Entre 5 y 8 FPS sostenido
Benchmark Flash: Entre 48 y 51 FPS sostenido
Mozilla Firefox 4.0.1-r1 bajo Gentoo Linux
Valores al doble en todas las pruebas menos en la de Flash
Opera 11.11 bajo Gentoo Linux
Benchmark HTML: Entre 50 y 55 FPS sostenidos
Benchmark Canvas: Entre 80 y 90 FPS sostenidos
Benchmark SVG: Entre 18 y 22 FPS sostenidos
Benchmark Flash: Entre 46 y 50 FPS sostenidos
Y estoy seguro de que con IE 9 los resultados serán parecidos a los de Opera o Chromium. Si alguien puede pasar el Benchmark y colgar sus resultados estaríamos enormemente agradecidos.
-- editado por última vez a las 15:11
IE9:
Benchmark HTML: Entre 51 y 59 FPS sostenidos.
Benchmark Canvas: Entre 93 y 104 FPS sostenidos.
Benchmark SVG: Entre 75 y 83 FPS sostenidos.
Benchmark Flash: 40 FPS sostenidos.
Gracias Jhonny, estaba seguro de que los resultados de IE9 eran parecidos a los de Chrome pero en la máquina virtual nada me pasaba de 36 FPS :)
Un saludo.
Yo saco resultados en la linea del benchmark.
http://spreadsheets.google.com/ccc?key=0AuE1_QN_mm71dGlKaC16MmE4ZFRhXzVXQjcyUElpWGc&hl=en
A bajo numero de elementos, resultados parecidos, aumentando elementos flash aumenta el rendimiento, con diferencias de mas del 300% a partir de 2500 elementos.
De todas formas es un test de alcance muy limitado. Aunque los resultados son coherentes.
saludos!
Hombre si te parece sacalo tb con Netscape Communicator 7...
El problema de esos resultados es que no son están realizados con navegadores actuales mserranom.
Un saludo.
Tu frase tiene un punto y aparte encima y otro debajo. Si quieres añadir contexto puedes corregirlo con algo asi:
"Como puedes comprobar, el potencial de canvas es muy superior a nada que exista actualmente para construir aplicaciones como la anterior bien sea en forma de plugin o con frameworks JavaScript.".
Afirmación que en mi experiencia también es falsa, ya que no veo nada en CloudIDE que no se pueda hacer igual en funcionalidad con Flex. Pero bueno, eso si seria materia de discusión.
saludos!
El contexto está implícito no es necesario añadirlo de forma explícita, creo que se entiende perfectamente.
Me parece muy bien que desde tu experiencia esa afirmación te parezca falsa, la última vez que lo revisé, el pensamiento único no estaba implantado aún :)
Saludos.
En fin, si tu ves que que el contexto esté implícito tendré que ir a clases de lengua, a ver si lo reaprendo algo.
Un saludo.
¿ACE usa canvas? mmmmm, a mi me da que no...
Supuestamente es el sucesor de Skywriter, vamos que está basado en Skywritter (Bespin) no me he parado a mirar el código pero Skywriter si usa
canvas.Skywriter
Al final me he puesto a mirar y he encontrado la noticia en la que dicen que Skywriter se integra en Ace y parece ser que usa el DOM para dibujar el texto a diferencia de Skywriter.
Gracias por el aviso macdav, en cuanto tenga un rato actualizo tanto la screenshot como el bloque del artículo donde se habla de Ace para hablar de Skywriter.
Un saludo.
Una cosa a tener en cuenta.
El elemento <canvas> tiene los atributos width y height pero esto no son los que determinan el tamaño en pantalla del elemento. Determinan el tamaño del lienzo. El tamaño que ocupa en pantalla se puede establecer mediante CSS o inline style.
Esto produce que si el lienzo es más grande que el tamaño del elemento, el lienzo se estire y se contraiga. A tener en cuenta por el tema de las coordenadas.
Escribir un comentario
Para hacer un comentario es necesario que te identifiques: ENTRA o conéctate con FacebookConnect