Aquí voy a compartir con vosotros algunas reflexiones que os pueden ayudar a la hora de elegir entre Canvas y SVG, o una mezcla de ambos.
Canvas y SVG son dos funcionalidades de gráficos tremendamente interesantes que aparecen con Internet Explorer 9 y ambas se benefician de la aceleración por hardware. Estas tecnologías nos pueden servir para resolver numerosos escenarios de uso de gráficos de las webs actuales. A la vista de la gran expectación que ha ocasionado Canvas, parece que la tendencia es ignorar SVG que, en muchos de los casos, es una opción mejor.
Breve resumen de Canvas y SVG
A continuación resumo a grandes rasgos lo que son SVG y Canvas para delimitar el análisis y determinar mejor cuándo conviene utilizar una tecnología de gráficos vectoriales u otra.
Comparación entre Canvas y SVG
Canvas | SVG |
Orientado al pixel (el canvas es básicamente un elemento de imagen con un API de dibujo) | Basado en el modelo de objetos (los elementos SVG son similares a los elementos HTML) |
Elemento HTML individual, similar en su comportamiento a la etiqueta <img> | Múltiples elementos gráficos que pasan a formar parte del Modelo de Objeto de Documento (DOM) |
La representación visual se crea y modifica por programa, mediante scripting | La representación visual se genera a partir del markup y se modifica mediante CSS o por programa, mediante scripting |
El modelo de evento/interacción con el usuario es rudimentario exclusivamente a nivel del elemento canvas; las interacciones se deben programar manualmente a partir de las coordenadas del ratón | El modelo de evento/interacción con el usuario se basa en el objeto a nivel de elementos gráficos primitivos líneas, rectángulos, rutas |
El API no soporta la accesibilidad; deben utilizarse, además del canvas, otras técnicas basadas en markup | El markup SVG y el modelo de objeto soportan accesibilidad de forma nativa |
A SVG se le conoce como un modelo de gráficos en modo retenido que persiste dentro de un modelo en memoria. De una manera similar a HTML, SVG genera un modelo de objeto de elementos, atributos y estilos. Cuando el elemento <svg> aparece en un documento HTML5, funciona igual que un bloque "inline" y forma parte del árbol de documento HTML.
Canvas es un mapa de bits con una interfaz de programación de aplicaciones (API) para gráficos en modo inmediato para poder dibujar sobre él. El canvas sigue el modelo de "dispara y vete" que restituye los gráficos directamente dentro de su mapa de bits y que no tiene consciencia de las formas que se han dibujado en el lienzo. Lo único que permanece es el mapa de bits resultante.
Podemos pensar que el Canvas viene a ser lo mismo que el API GDI de Windows, donde por programa podemos dibujar gráficos en la ventana, y SVG vendría a ser lo que es el lenguaje HTML con elementos, estilos, eventos y programación basada en DOM. Canvas se orienta a procedimiento y SVG es declarativo.
Escenarios de uso
En los apartados siguientes explico las ventajas y limitaciones desde el punto de vista técnico de ambas tecnologías, y también añado algunas orientaciones de sentido común para saber en qué momento interesan una u otra para una tarea concreta. En la ilustración siguiente se muestra el espectro de usos que va desde Canvas a SVG con un punto claro ambivalencia en el medio.
Espectro de casos de uso de tecnologías de gráficos Canvas y SVG
Documentos vectoriales complejos de alta fidelidad
Los documentos vectoriales complejos de alta fidelidad han sido y siguen siendo el campo natural de acción para SVG. Un elevado nivel de detalle en la presentación e impresión, tanto a nivel de objeto individual como embebido en una página web. La naturaleza declarativa de SVG es la base para la creación de herramientas o para la generación de formas tanto en el cliente como el servidor a partir de información almacenada en bases de datos.
Vemos un ejemplo tomado de la demo Diagramas del mundo real que se encuentra en el sitio Web Internet Explorer Test Drive:
La primera imagen muestra los diagramas, y la segunda muestra los mismos diagramas con una ampliación de la imagen del 1000%
Si lo que valoras es la conveniencia de observar un esquema de gran tamaño sobre el cual hay que profundizar en distintos grafos de detalle, o imprimir todo el documento en un formato de un tamaño concreto pero manteniendo las proporciones y la definición, la cualidad de "escalable" de los Gráficos Vectoriales Escalables (SVG por sus siglas en inglés Scalable Vector Graphics) se hace evidente. Es por esto que ponemos a los documentos vectoriales complejos de alta fidelidad en el extremo SVG del espectro
SVG como formato de imágenes
Otro uso frecuente de SVG es el de generación de imágenes estáticas dentro de la página web. Con los monitores actuales de alta densidad de pixels, los desarrolladores han de tener en cuenta la calidad de los gráficos. Las imágenes que se muestran a continuación representan posibles imágenes de viñetas correspondientes a listas desordenadas "<li>" cuyo estilo se determina mediante CSS. Las siguientes imágenes son prácticamente iguales en tamaño y presentación.
A la izquierda, un gráfico SVG y a la derecha, una imagen en formato PNG
Si el desarrollador quiere mostrar la imagen a una escala mayor, o si el usuario final utiliza una pantalla de muy alta resolución, la imagen raster aparece pixelada, y necesitará una versión de mayor tamaño de ese mismo archivo, para poder mantener la fidelidad a esta escala.
Gráfico SVG ampliado a la izquierda, imagen de 4K en formato PNG aumentada a la derecha
Por tanto, SVG nos puede servir como un sustituto aventajado de incluso las imágenes más sencillas en una página web. Sin embargo el Canvas no sirve como sustituto.
En el otro extremo del espectro, el canvas aporta velocidad a los escenarios de uso donde no se exige retener información de los elementos dibujados en pantalla. Cuando se introdujo por primera vez la etiqueta <canvas> se empezaron a diseñar experimentos muy divertidos. Yo los clasifico en tres categorías.
Manipulación de píxeles
Ya que Canvas tiene que ver fundamentalmente con el dibujo y manipulación a nivel de pixel de una superficie, existen ciertos experimentos y ejemplos de Canvas con sofisticados algoritmos que logran unos efectos gráficos realmente impresionantes, como por ejemplo simulación de rayos de luz reflejado o filtrados.
El ejemplo siguiente, llamado "Ray-Tracing" ha sido creado por Adam Burmister. En este experimento se genera una imagen a base de calcular el recorrido de los rayos de la luz por todo el campo de pixels en un plano de la imagen y simulando los efectos de su reflejo sobre otros objetos virtuales dentro de la escena.
El propio autor avisa: "consume mucha CPU. El navegador puede que parezca que deja de funcionar". Así que, aunque mediante el API de canvas, se pueden generar imágenes como esta, no parece lo más recomendable. El propio autor del sitio web Adam Burmister lo resume, "Ray-Tracing [es] la peor aplicación jamás escrita en JavaScript."
Lo mismo se puede decir para otra manipulación de píxeles a nivel de toda la escena. La siguiente función sustituye los pixels de color verde en un canvas con pixels de otro canvas de tamaño idéntico. Una función como esta puede servir para crear un efecto que, en el mundo del vídeo, se llama "chroma".
function GreenScreenAtoB(a, b) {
var aImageData = a.getImageData(0, 0, a.canvas.width, a.canvas.height);
var bImageData = b.getImageData(0, 0, b.canvas.width, b.canvas.height);
var aPixels = aImageData.data;
var bPixels = bImageData.data;
if (aPixels.length != bPixels.length) {
window.alert("Canvases do not have the same number of pixels");
return bImageData;
}
var pixelCount = bPixels.length;
for (var pixelIndex = 0; pixelIndex < pixelcount; pixelIndex += 4) {
// grab the RGBA components of each pixel in b
var r = bPixels[pixelIndex + 0];
var g = bPixels[pixelIndex + 1];
var b = bPixels[pixelIndex + 2];
var a = bPixels[pixelIndex + 3];
// if the b pixel is green, replace it with a pixel from a
if (r == 0 && g == 255 && b == 0 && a == 255) {
bPixels[pixelIndex + 0] = aPixels[pixelIndex + 0];
bPixels[pixelIndex + 1] = aPixels[pixelIndex + 1];
bPixels[pixelIndex + 2] = aPixels[pixelIndex + 2];
bPixels[pixelIndex + 3] = aPixels[pixelIndex + 3];
}
}
return bImageData;
}
Era un experimento bastante divertido, pero como ocurría con el ejemplo de reflexión de la luz "ray-tracing" anterior, su rendimiento en las máquinas actuales es más bien malo. Los traigo a colación aquí sobre todo por una razón: esta manipulación de pixels es, sencillamente, imposible con SVG. Este es el factor diferencial entre ambas tecnologías. Una manipula píxeles, la otra manipula objetos dentro de un modelo.
Ya se trate de crear imágenes realistas a partir de gráficos vectoriales que en su origen son sencillos, o para hacer efectos tipo chroma con vídeos, estos escenarios de uso de gráficos, en la mayoría de ocasiones, simplemente no están aún maduros como para ponerlos en la Web a día de hoy. No obstante, otros casos de uso sí ofrecen una respuesta buena (por ejemplo la aplicación de filtros para eliminar los ojos rojos en las fotos). Estos casos de manipulación de pixeles quedarían en el extremo de la izquierda de nuestro espectro, como ejemplos inequívocos de uso de canvas.
Escenarios mixtos y ambivalentes
El grupo más interesante de casos de uso no se decanta de manera clara por ninguna de las dos tecnologías. Los podemos ejemplificar con dos escenarios básicos: diagramas/gráficos/mapas y juegos en dos dimensiones.
Los gráficos y diagramas requieren gráficos vectoriales, y aquí pueden valer tanto Canvas como SVG. No obstante, SVG es a menudo una opción más conveniente dadas sus cualidades naturales.
Escenarios de uso de SVG con gráficos, diagramas y mapas
Algunas de las familias más conocidas de gráficos y diagramas que podemos ver en la Web son:
- Los diagramas de flujo y organigramas interactivos
- Mapas interactivos y diseño de rutas óptimas
- Planos de construcción y distribución en planta
- Esquemas de ingeniería
- Mapas de ubicación de asientos en líneas aéreas y organización de eventos
- Gráficos financieros o de cualquier otra naturaleza a partir de datos (gráficos de barras, columnas, líneas, tartas, donuts, etc.)
En todos estos casos la tecnología más adecuada es SVG:
- Estos gráficos se pueden generar fácilmente a partir de datos mediante transformaciones de XML a SVG
- las versiones estáticas se pueden exportar mediante herramientas (por ejemplo Inkscape, Adobe Illustrator, Microsoft Visio y algunos programas de CAD)
- Exigen precisión en la interacción con el usuario
- Los creadores de las webs pueden personalizar módulos de otros fabricantes utilizando plantillas de estilos CSS
- Cumplen con los requisitos de accesibilidad
Para ilustrar de manera más precisa todo esto, vamos a ver un ejemplo donde seleccionamos un estado en un mapa de Estados Unidos.
El mapa detallado de Alaska que se muestra aquí es de dominio público y se puede encontrar en Wikimedia Commons.
En SVG el estado de Alaska está representado como un elemento <path> con aproximadamente 162.500 elementos de datos de geometría en su atributo "d".
<path id="AK" fill="#cdc3cc" d="M 777.5514,1536.1543 C 776.4904,1535.0933 776.7795,1530.0041 777.9416,1529.2859 C 781.3258,1527.1943 787.2657,1532.4522 784.8317,1535.3849 ..." />
Si empleamos el canvas, esta misma forma se puede crear mediante una serie de llamadas en Javascript:
function drawAlaska() {
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.moveTo(777.5514, 1536.1543);
ctx.bezierCurveTo(776.4904, 1535.0933, 776.7795, 1530.0041, 777.9416, 1529.2859);
ctx.bezierCurveTo(781.3258, 1527.1943, 787.2657, 1532.4522, 784.8317,1535.3849);
//
// 2,875 more path-drawing directives
//
ctx.bezierCurveTo(1689.8261, 12.13753, 1689.1395, 12.17333, 1685.8848, 10.52683);
ctx.closePath();
ctx.fillStyle = "#cdc3cc";
ctx.fill();
}
En realidad necesitamos 2.878 instrucciones de dibujo de líneas (moveTo, lineTo y bezierCurveTo) para poder dibujar este mapa de Alaska. Obviamente, se pueden dibujar versiones de baja resolución de este mapa. Y para dibujar los estados de Wyoming y Colorado, se necesitan bastantes menos líneas de código ?
Las aplicaciones de mapas basadas en SVG normalmente incluyen una experiencia de interactividad con respuesta a eventos de paso del cursor por encima, selección de áreas, desplazamiento de unos elementos a otros mediante el tabulador y cambios de escala. Esta operaciones solo necesitan conceptos HTML de escasa complejidad cuando utilizamos SVG, como por ejemplo para procesar un evento de ratón:
<path id="AK" fill="#cdc3cc" onmousedown="window.alert('Alaska');" d="M 777.5514,1536.1543 ..." />
O para crear un efecto de iluminación al pasar el cursor, que se puede hacer con CSS:
path#AK:hover { fill: yellow; }
Un ejemplo de este tipo de mapas interactivos se puede ver en la demo de Testdrive llamada Atlas zur Europawahl 2004 in Deutschland, una presentación sobre mapa de los resultados de las elecciones al Parlamento Europeo de 2004 en Alemania.
En un canvas, la creación de cualquiera de estos efectos nos obliga a programar por nuestros propios medios la detección de los eventos y la captura de las coordenadas del cursor dentro del objeto generador del evento de ratón. Aquí ya no podemos utilizar el contexto de la forma. Aunque existe el API isPointOnPath(), solo se aplica al último trazo creado.
El código puede existir de hecho existe- en forma de librerías gráficas que permiten la detección de eventos concretos en los gráficos utilizando los datos de los pixels para identificar el paso del cursor y las pulsaciones del ratón, y son plenamente funcionales. Existen también para SVG y lograremos un mejor rendimiento si están diseñadas para aprovechar las características propias de SVG.
Diagramas y gráficos con Canvas
También el canvas tiene sus opciones cuando se trata de diagramas y gráficos. Para fijar el contexto en este caso, tenemos que comparar el rendimiento de SVG y de Canvas.
Algunas veces se producen influencias externas que nos obligan a elegir una tecnología que es, o en principio debería ser, independiente de la funcionalidad. En el caso de SVG y Canvas, hay dos elementos diferenciales básicos.
El conocimiento del desarrollador, sus competencias y los elementos de apoyo que tiene a mano juegan un papel muy importante a la hora de decantarse por una u otra tecnología. Si en el caso del desarrollo de un juego los programadores suelen tener un excelente nivel de conocimientos sobre las APIs de gráficos a bajo nivel y un conocimiento limitado de las tecnologías Web, la tecnología que probablemente elegirán será Canvas (vemos esto luego con más detalle). Si se trata de migrar juegos, existen herramientas que soportan la conversión desde implementaciones de terceros al Canvas.
Si el rendimiento es un factor esencial, a menudo en el rango de los milisegundos, será preciso comparar el rendimiento de ambas tecnologías. Esto no quiere decir que Canvas, que habitualmente se considera de alto rendimiento, sea la opción natural. No obstante, en el caso de las aplicaciones que involucran grandes cantidades de datos que deben representarse a nivel de pixel, el Canvas es, sin lugar a dudas, la mejor opción.
El mapa del tiempo que aparece aquí no requiere un área de dibujo muy grande y el número de objetos en pantalla es bastante elevado. Con Canvas estos se puede dibujar de manera rápida sin el coste que representa la actualización del árbol del DOM.
Si bien la imagen anterior puede también hacerse con SVG utilizando elementos como círculos y elipses para dibujar los puntos, el tiempo necesario para cargar miles de elementos en el DOM lo hacen, inevitablemente, mucho más lento. Siempre que veamos un número muy grande de pixels o imágenes, una buen recomendación es utilizar la tecnología de Canvas tanto si se trata de astronomía como de movimientos de biología celular o espectros de modulación de la voz. Los límites de velocidad en la visualización de los datos los marcan la velocidad de la CPU y la implementación del Canvas y del motor de Javascript que utilicemos.
Juegos en dos dimensiones
Los juegos ocasionales son el escenario más complicado de analizar. Algunas observaciones preliminares:
- Las librerías de juegos incluyen APIs de gráficos de bajo nivel optimizadas
- Las competencias de los desarrolladores en el mundo de los juegos están muy orientadas hacia el uso de estas APIs de bajo nivel
- Muchos juegos se basan casi exclusivamente o en una gran parte, en imágenes o sprites
- Los fabricantes como Adobe empiezan a dar soporte a Canvas como un formato de exportación
- Los juegos ocasionales no suelen requerir técnicas sofisticadas de captura de eventos de ratón
- Los juegos ocasionales no tienen normalmente un número exageradamente grande de "objetos"
En las librerías gráficas, como por ejemplo los conocidos motores de efectos de física, el modelo de gráficos es independiente y los gráficos se convierten en un detalle de la implementación. Los elementos de geometría como bordes, velocidades, tamaños y posiciones se envían a los motores y éstos responden en consecuencia con velocidades, colisiones y posiciones. Los gráficos se utilizan únicamente para representar en pantalla la escena previamente calculada.
La idea de que la parte gráfica sea independiente de la lógica de juego está bien demostrada en dos juegos desarrollados por el mismo autor, con el objetivo de ilustrar las capacidades de SVG y Canvas: SVG-oids y canvas-pinball.
Aunque ambos juegos y sus lógicas son distintos, ambos utilizan el mismo motor de física, que sirve para controlar las posiciones, colisiones, velocidades y otros aspectos físicos de sus componentes. En un caso se utiliza SVG para dibujar (o mover) los elementos del juego, y en el otro, se redibujan sobre un Canvas.
La mayor parte de los juegos ocasionales en 2D que podemos ver actualmente para HTML5 utilizan el Canvas, por lo que vamos a dejar este caso de uso en el lado del Canvas a la izquierda del punto de cruce.
El escenario mixto
Los juegos ocasionales también caen dentro del escenario mixto porque podemos aprovechar una combinación de características de ambas tecnologías. En el caso de la detección fácil de eventos de ratón e interacción con el usuario, una capa casi opaca de geometrías SVG se puede utilizar para colocar los elementos mientras que un Canvas por debajo puede servir para ubicar de manera más rápida las imágenes principales (por ejemplo los paisajes de fondo) y generar animaciones en tiempo real.
Cada vez encontramos más experiencias aparte del segmento de los juegos ocasionales en las cuales es más interesante el modelo de uso mixto. Cuando en un escenario nos encontramos con la necesidad de disponer gráficos dinámicos y animaciones con calidad alta (Canvas) junto con una interacción fuerte con el usuario (SVG), lo recomendable es utilizar las dos tecnologías. Esto es lo que se puede ver en el sitio web Brain Power de uno de nuestros partners, que forma parte del catálogo de sitios recomendados en The Beauty of the Web. El sitio Brain Power como algunos otros más recomendados también en The Beauty of the Web es un ejemplo de delicado equilibrio.
Para resolver la interacción del usuario y visualizar las partes del cerebro, en este sitio se aprovechan las geometrías de alto nivel de SVG:
<polygon id="SensoryCortex" points="253,80,266,93,..." style="fill: rgba(0,0,0,0)" />
Para las animaciones y efectos especiales en tiempo real, se utilizan canvas:
<canvas id="cnvDisplay" width="1920" height="1099" style="position:absolute;" />
Conclusión
El análisis de las tecnologías de gráficos vectoriales disponibles en las últimas versiones de los navegadores nos muestra cómo se pueden crear nuevos escenarios de uso utilizando las tecnologías Web estándar de forma interactiva. Te recomiendo los siguientes vídeos donde se ofrecen más detalles sobre el desarrollo con Canvas y SVG:
La evolución de la Web sigue su curso, incorporando gráficos cada vez más sofisticados como un componente natural. He explicado aquí mi punto de vista sobre la aplicación de estas tecnologías a casos de uso concretos. Al final, tanto Canvas como SVG son componentes muy importantes dentro de una Web cada vez más volcada hacia los gráficos avanzados con HTML5.
Nos encantaría conocer cómo estás aplicando estas nuevas tecnologías HTML5 en tus sitios Web. Incluye las URLs y por favor, comprueba que tu página funciona en IE9 incluyendo el meta doctype, <!DOCTYPE html>, y utiliza la detección de características en vez de la detección del navegador para saber si están soportados el Canvas o el SVG.
Patrick Dengler
Senior Program Manager, Internet Explorer