El elemento Canvas de HTML5 vs SVG vs div


¿Cuál es el mejor enfoque para crear elementos sobre la marcha y poder moverlos? Por ejemplo, digamos que quiero crear un rectángulo, un círculo y un polígono y luego seleccionar esos objetos y moverlos.

Entiendo que HTML5 proporciona tres elementos que pueden hacer esto posible: svg, canvas y div. Para lo que quiero hacer, ¿cuál de esos elementos proporcionará el mejor rendimiento?

Para comparar estos enfoques, I estaba pensando en crear tres páginas web visualmente idénticas que cada una tenga un encabezado, pie de página, widget y contenido de texto en ellas. El widget en la primera página se crearía completamente con el elemento canvas, el segundo completamente con el elemento svg, y el tercero con el elemento div simple, HTML y CSS.

Author: Manfred Radlwimmer, 0000-00-00

8 answers

La respuesta corta:

SVG sería más fácil para usted, ya que la selección y el movimiento ya están integrados. Los objetos SVG son objetos DOM, por lo que tienen controladores de "clic", etc.

Los DIVs están bien pero son torpes y tienen un rendimiento horrible cargando grandes números.

Canvas tiene el mejor rendimiento, pero debe implementar todos los conceptos de estado administrado (selección de objetos, etc.) usted mismo, o usar una biblioteca.


El largo respuesta:

HTML5 Canvas es simplemente una superficie de dibujo para un mapa de bits. Se configura para dibujar (Digamos con un color y un grosor de línea), dibujar esa cosa, y luego el Lienzo no tiene conocimiento de esa cosa: no sabe dónde está o qué es lo que acabas de dibujar, son solo píxeles. Si quieres dibujar rectángulos y hacer que se muevan o sean seleccionables, entonces tienes que codificar todo eso desde cero, incluyendo el código para recordar que los dibujaste.

SVG por el otro hand debe mantener referencias a cada objeto que renderiza. Cada elemento SVG / VML que cree es un elemento real en el DOM. De forma predeterminada, esto le permite mantener un seguimiento mucho mejor de los elementos que crea y facilita el manejo de cosas como eventos del ratón de forma predeterminada, pero se ralentiza significativamente cuando hay un gran número de objetos

Esas referencias SVG DOM significan que parte del juego de pies de tratar con las cosas que dibujas se hace por ti. Y SVG es más rápido al renderizar objetosrealmente grandes, pero más lentos al renderizar muchos objetos.

Un juego probablemente sería más rápido en Canvas. Un programa de mapas enorme probablemente sería más rápido en SVG. Si desea utilizar Canvas, tengo algunos tutoriales sobre cómo poner en marcha y ejecutar objetos móviles aquí.

Canvas sería mejor para cosas más rápidas y manipulación de mapas de bits pesados (como la animación), pero tomará más código si desea mucha interactividad.

He corrido un montón de números en HTML DIV-hecho dibujo versus lienzo-hecho dibujo. Podría hacer un gran post sobre los beneficios de cada uno, pero voy a dar algunos de los resultados relevantes de mis pruebas a considerar para su aplicación específica:

Hice páginas de prueba Canvas y HTML DIV, ambas tenían nodos móviles."Los nodos Canvas eran objetos que creé y rastreé en Javascript. Los nodos HTML eran Divs móviles.

He añadido 100.000 nodos a cada una de mis dos pruebas. Se desempeñaron de manera bastante diferente:

La prueba HTML ficha tomó para siempre para cargar (cronometrado en un poco menos de 5 minutos, Chrome pidió matar a la página la primera vez). Administrador de tareas de Chrome dice que la ficha está ocupando 168MB. Ocupa 12-13% de tiempo de CPU cuando lo estoy mirando, 0% cuando no estoy mirando.

La pestaña Canvas se carga en un segundo y ocupa 30MB. También ocupa el 13% del tiempo de CPU todo el tiempo, independientemente de si uno lo está mirando o no. (edición de 2013: En su mayoría lo han arreglado)

Arrastrar en la página HTML es más suave, lo que es esperado por el diseño, ya que la configuración actual es volver a dibujar TODO cada 30 milisegundos en la prueba de Canvas. Hay muchas optimizaciones para Canvas para esto. (la invalidación del lienzo es la más fácil, también recorta regiones, redibuja selectiva, etc.. solo depende de cuánto te apetezca implementar)

No hay duda de que podría conseguir que Canvas sea más rápido en la manipulación de objetos como los divs en esa prueba simple, y por supuesto mucho más rápido en la carga tiempo. Dibujar / cargar es más rápido en Canvas y también tiene mucho más espacio para optimizaciones (es decir, excluir cosas que están fuera de la pantalla es muy fácil).

Conclusión:

  • SVG es probablemente mejor para aplicaciones y aplicaciones con pocos elementos (menos de 1000? Depende realmente)
  • Canvas es mejor para miles de objetos y una manipulación cuidadosa, pero se necesita mucho más código (o una biblioteca) para despegar.
  • HTML Divs son torpes y no escalan, haciendo un el círculo solo es posible con esquinas redondeadas, haciendo formas complejas es posible, pero involucra cientos de diminutos divs de píxeles de ancho. La locura sobreviene.
 491
Author: Simon Sarris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-15 16:14:56

Para agregar a esto, he estado haciendo una aplicación de diagrama, e inicialmente empecé con canvas. El diagrama consta de muchos nodos, y pueden ser bastante grandes. El usuario puede arrastrar elementos en el diagrama.

Lo que encontré fue que en mi Mac, para imágenes muy grandes, SVG es superior. Tengo un MacBook Pro 2013 13" Retina, y funciona el violín a continuación bastante bien. La imagen es de 6000x6000 píxeles, y tiene 1000 objetos. Una construcción similar en canvas era imposible de animar para me cuando el usuario estaba arrastrando objetos en el diagrama.

En las pantallas modernas también tienes que tener en cuenta diferentes resoluciones, y aquí SVG te da todo esto de forma gratuita.

Violín: http://jsfiddle.net/knutsi/PUcr8/16/

Pantalla completa: http://jsfiddle.net/knutsi/PUcr8/16/embedded/result /

var wiggle_factor = 0.0;
nodes = [];

// create svg:
var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svg.setAttribute('style', 'border: 1px solid black');
svg.setAttribute('width', '6000');
svg.setAttribute('height', '6000');

svg.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink",
    "http://www.w3.org/1999/xlink");

document.body.appendChild(svg);


function makeNode(wiggle) {
    var node = document.createElementNS("http://www.w3.org/2000/svg", "g");
    var node_x = (Math.random() * 6000);
    var node_y = (Math.random() * 6000);
    node.setAttribute("transform", "translate(" + node_x + ", " + node_y +")");

    // circle:
    var circ = document.createElementNS("http://www.w3.org/2000/svg", "circle");
    circ.setAttribute( "id","cir")
    circ.setAttribute( "cx", 0 + "px")
    circ.setAttribute( "cy", 0 + "px")
    circ.setAttribute( "r","100px");
    circ.setAttribute('fill', 'red');
    circ.setAttribute('pointer-events', 'inherit')

    // text:
    var text = document.createElementNS("http://www.w3.org/2000/svg", "text");
    text.textContent = "This is a test! ÅÆØ";

    node.appendChild(circ);
    node.appendChild(text);

    node.x = node_x;
    node.y = node_y;

    if(wiggle)
        nodes.push(node)
    return node;
}

// populate with 100 nodes:
for(var i = 0; i < 1000; i++) {
    var node = makeNode(true);
    svg.appendChild(node);
}

// make  one mapped to mouse:
var bnode = makeNode(false);
svg.appendChild(bnode);

document.body.onmousemove=function(event){
    bnode.setAttribute("transform","translate(" +
        (event.clientX + window.pageXOffset) + ", " +
        (event.clientY + window.pageYOffset) +")");
};

setInterval(function() {
    wiggle_factor += 1/60;
    nodes.forEach(function(node) {

        node.setAttribute("transform", "translate(" 
                          + (Math.sin(wiggle_factor) * 200 + node.x) 
                          + ", " 
                          + (Math.sin(wiggle_factor) * 200 + node.y) 
                          + ")");        
    })
},1000/60);
 33
Author: knut,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-06 14:31:43

Conocer las diferencias entre SVG y Canvas sería útil para seleccionar el correcto.

Lienzo

  • Depende de la resolución
  • No hay soporte para controladores de eventos
  • Capacidades de representación de texto pobres
  • Puede guardar la imagen resultante como .png or .jpg
  • Muy adecuado para juegos gráficos intensivos

SVG

  • Resolución independiente
  • Soporte para controladores de eventos
  • Más adecuado para aplicaciones con grandes áreas de representación (Google Maps)
  • Renderizado lento si es complejo (cualquier cosa que use mucho el DOM será lento)
  • No es adecuado para la aplicación del juego
 19
Author: Leo The Four,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-28 14:14:06

Estoy de acuerdo con las conclusiones de Simon Sarris:

He comparado algunas visualizaciones en Protovis (SVG) con Processingjs (Canvas) que muestran > 2000 puntos y processingjs es mucho más rápido que protovis.

El manejo de eventos con SVG es, por supuesto, mucho más fácil porque puede adjuntarlos a los objetos. En Canvas tienes que hacerlo manualmente (comprobar la posición del ratón, etc.) pero para una interacción simple no debería ser difícil.

También está el dojo.gfx biblioteca de la dojo toolkit. Proporciona una capa de abstracción y puede especificar el renderizador (SVG, Canvas, Silverlight). Eso también podría ser una opción viable, aunque no se cuánta sobrecarga agrega la capa de abstracción adicional, pero hace que sea fácil codificar interacciones y animaciones y es independiente del renderizador.

Aquí hay algunos interesantes puntos de referencia:

 18
Author: Ümit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-02 07:03:33

Solo mis 2 centavos con respecto a la opción divs.

Famous/Infamous y SamsaraJS (y posiblemente otros) usan divs no anidados absolutamente posicionados (con contenido HTML/CSS no trivial), combinados con matrix2d/matrix3d para el posicionamiento y las transformaciones 2D/3D, y logran una estabilidad de 60 FPS en hardware móvil moderado, por lo que argumentaría en contra de que divs sea una opción lenta.

Hay un montón de grabaciones de pantalla en Youtube y en otros lugares, de material 2D/3D de alto rendimiento que se ejecuta en el navegador con todo siendo un elemento DOM en el que puede Inspeccionar el elemento, a 60 FPS (mezclado con WebGL para ciertos efectos, pero no para la parte principal del renderizado).

 15
Author: Erik Allik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-10 10:02:33

Para sus propósitos, recomiendo usar SVG, ya que obtiene eventos DOM, como el manejo del mouse, incluyendo arrastrar y soltar, incluido, no tiene que implementar su propio redibujo y no tiene que realizar un seguimiento del estado de sus objetos. Use Canvas cuando tenga que manipular imágenes de mapa de bits y use un div regular cuando quiera manipular cosas creadas en HTML. En cuanto al rendimiento, encontrará que los navegadores modernos ahora están acelerando los tres, pero que canvas ha recibido la mayor parte atención hasta ahora. Por otro lado, lo bien que escribes tu javascript es fundamental para obtener el máximo rendimiento con canvas, por lo que todavía recomendaría usar SVG.

 13
Author: Gaurav,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-04 11:55:35

Aunque todavía hay algo de verdad en la mayoría de las respuestas anteriores, creo que merecen una actualización:

A lo largo de los años, el rendimiento de SVG ha mejorado mucho y ahora hay transiciones y animaciones CSS aceleradas por hardware para SVG que no dependen del rendimiento de JavaScript en absoluto. Por supuesto, el rendimiento de JavaScript también ha mejorado y con él el rendimiento de Canvas, pero no tanto como SVG mejoró. También hay un "niño nuevo" en el bloque que está disponible en casi todos los navegadores actuales y eso es WebGL . Para usar las mismas palabras que Simon usó anteriormente: supera a Canvas y SVG sin duda. Sin embargo, esto no significa que deba ser la tecnología de referencia, ya que es una bestia para trabajar y solo es más rápido en casos de uso muy específicos.

En mi humilde opinión para la mayoría de los casos de uso actuales, SVG ofrece la mejor relación rendimiento/usabilidad. Las visualizaciones deben ser realmente complejas (con respecto al número de elementos) y realmente simples al mismo tiempo (por elemento) para que Canvas y aún más WebGL realmente brillen.

En esta respuesta a una pregunta similarestoy proporcionando más detalles, por qué creo que la combinación de las tres tecnologías a veces es la mejor opción que tiene.

 6
Author: Sebastian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-04 06:26:58

Mientras busco en Google, encuentro una buena explicación sobre el uso y la compresión de SVG y Canvas en http://teropa.info/blog/2016/12/12/graphics-in-angular-2.html

Espero que ayude:

  • SVG, al igual que HTML, utiliza representación retenida: Cuando queremos dibujar un rectángulo en la pantalla, utilizamos declarativamente un elemento en nuestro DOM. El navegador dibujará un rectángulo, pero también creará un SVGRectElement en memoria objeto que representa el rectángulo. Este objeto es algo que se queda para que lo manipulemos-es conservar. Podemos asignarle diferentes posiciones y tamaños con el tiempo. También podemos adjuntar oyentes de eventos para que sea interactivo.
  • Canvas usa representación inmediata: Cuando dibujamos un rectángulo, el navegador renderiza inmediatamente un rectángulo en la pantalla, pero hay nunca va a haber ningún "objeto rectángulo" que lo represente. Hay sólo un montón de píxeles en el búfer de lienzo. No podemos mover el rectángulo. Sólo podemos dibujar otro rectángulo. No podemos responder a clics u otros eventos en el rectángulo. Solo podemos responder a eventos en el lienzo completo .

Así que canvas es una API más restrictiva y de bajo nivel que SVG. Pero hay un al revés de eso, que es que con canvas puedes hacer más con el la misma cantidad de recursos. Porque el navegador no tiene que crear y mantener el objeto en memoria gráfico de todas las cosas que tenemos dibujado, necesita menos memoria y recursos de computación para dibujar el mismo escena visual. Si usted tiene una visualización muy grande y compleja a dibujar, Lienzo puede ser su boleto.

 1
Author: Alireza Fattahi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-03 07:37:46