| 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.
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
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.
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.
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.
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.
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.
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.
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.
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;" />
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.
![]() jbdr | escenario mixto | 17/1/2012 |