541 Stimmen

HTML5 Canvas vs. SVG vs. div

Wie lassen sich Elemente am besten im laufenden Betrieb erstellen und verschieben? Nehmen wir an, ich möchte ein Rechteck, einen Kreis und ein Polygon erstellen und dann diese Objekte auswählen und verschieben.

Soweit ich weiß, bietet HTML5 drei Elemente, die dies möglich machen können: svg , Leinwand y div . Welches dieser Elemente bietet die beste Leistung für das, was ich tun möchte?

Um diese Ansätze zu vergleichen, dachte ich an die Erstellung von drei visuell identischen Webseiten, die jeweils eine Kopfzeile, eine Fußzeile, ein Widget und einen Textinhalt enthalten. Das Widget auf der ersten Seite würde vollständig mit dem canvas Element, das zweite vollständig mit dem svg Element, und das dritte mit dem einfachen div Element, HTML und CSS.

645voto

Simon Sarris Punkte 60248

Die kurze Antwort:

SVG wäre einfacher für Sie, da die Auswahl und das Verschieben bereits eingebaut sind. SVG-Objekte sind DOM-Objekte, also haben sie "Klick"-Handler, etc.

DIVs sind okay, aber klobig und haben furchtbar Leistungsbelastung bei großen Zahlen.

Canvas hat mit Abstand die beste Leistung, aber Sie müssen alle Konzepte des verwalteten Zustands (Objektauswahl usw.) selbst implementieren oder eine Bibliothek verwenden.


Die lange Antwort:

HTML5 Canvas ist einfach eine Zeichenfläche für eine Bitmap. Man richtet sich zum Zeichnen ein (z. B. mit einer Farbe und Linienstärke), zeichnet das Ding, und dann hat der Canvas keine Kenntnis von diesem Ding: Er weiß nicht, wo es ist oder was es ist, das man gerade gezeichnet hat, es sind nur Pixel. Wenn Sie Rechtecke zeichnen wollen und diese sich bewegen oder auswählbar sein sollen, müssen Sie all das von Grund auf neu programmieren, einschließlich den Code, um sich daran zu erinnern, dass Sie sie gezeichnet haben.

SVG hingegen muss Verweise auf jedes Objekt, das es wiedergibt, beibehalten. Jedes SVG/VML-Element, das Sie erstellen, ist ein echtes Element im DOM. Standardmäßig können Sie so die von Ihnen erstellten Elemente viel besser verfolgen und Dinge wie Mausereignisse einfacher handhaben, aber es verlangsamt sich erheblich, wenn es eine große Anzahl von Objekten gibt

Diese SVG-DOM-Referenzen bedeuten, dass ein Teil der Arbeit mit den von Ihnen gezeichneten Objekten für Sie erledigt ist. Und SVG ist schneller beim Rendern sehr groß Objekte, aber langsamer beim Rendern viele Objekte.

Ein Spiel würde in Canvas wahrscheinlich schneller sein. Ein großes Kartenprogramm wäre in SVG wahrscheinlich schneller. Wenn Sie Canvas verwenden möchten, finden Sie hier einige Anleitungen, wie Sie bewegliche Objekte zum Laufen bringen können aquí .

Canvas wäre besser für schnellere Dinge und schwere Bitmap-Manipulation (wie Animation), aber wird mehr Code nehmen, wenn Sie viel Interaktivität wollen.

Ich habe eine Reihe von Zahlen zu HTML DIV-gefertigten Zeichnungen gegenüber Canvas-gefertigten Zeichnungen durchgeführt. Ich könnte einen riesigen Beitrag über die Vorteile der beiden machen, aber ich werde einige der relevanten Ergebnisse meiner Tests geben, um für Ihre spezifische Anwendung zu berücksichtigen:

Ich habe Canvas- und HTML-DIV-Testseiten erstellt, beide hatten bewegliche "Knoten". Canvas-Knoten waren Objekte, die ich in Javascript erstellt und verfolgt habe. HTML-Knoten waren bewegliche Divs.

Ich habe zu meinen beiden Tests jeweils 100.000 Knoten hinzugefügt. Sie haben ganz unterschiedlich abgeschnitten:

Die HTML-Test-Registerkarte brauchte ewig, um zu laden (knapp 5 Minuten, Chrome bat beim ersten Mal darum, die Seite zu beenden). Der Task-Manager von Chrome zeigt an, dass die Registerkarte 168 MB beansprucht. Sie beansprucht 12-13% der CPU-Zeit, wenn ich sie betrachte, 0%, wenn ich sie nicht betrachte.

Die Registerkarte Canvas wird in einer Sekunde geladen und nimmt 30 MB ein. Außerdem beansprucht sie ständig 13 % der CPU-Zeit, unabhängig davon, ob man sie anschaut oder nicht. (2013 edit: Sie haben das größtenteils behoben)

Das Ziehen auf der HTML-Seite ist flüssiger, was vom Design her erwartet wird, da die aktuelle Einstellung im Canvas-Test alle 30 Millisekunden ALLES neu zeichnet. Es gibt viele Optimierungen für Canvas, die dies ermöglichen. (Canvas-Invalidierung ist die einfachste, auch Clipping-Regionen, selektives Redrawing, usw.. hängt nur davon ab, wie viel Sie implementieren möchten)

Es besteht kein Zweifel daran, dass Canvas bei der Objektmanipulation schneller sein könnte als die Divs in diesem einfachen Test, und natürlich viel schneller in der Ladezeit. Zeichnen/Laden ist schneller in Canvas und hat viel mehr Raum für Optimierungen, auch (dh, ausschließen Dinge, die außerhalb des Bildschirms sind, ist sehr einfach).

Schlussfolgerung:

  • SVG ist wahrscheinlich besser für Anwendungen und Anwendungen mit wenigen Elementen (weniger als 1000? Kommt wirklich darauf an)
  • Canvas eignet sich besser für Tausende von Objekten und sorgfältige Manipulationen, aber es ist viel mehr Code (oder eine Bibliothek) erforderlich, um es in Gang zu bringen.
  • HTML-Divs sind klobig und lassen sich nicht skalieren, ein Kreis lässt sich nur mit abgerundeten Ecken erstellen, komplexe Formen sind möglich, erfordern aber Hunderte winziger, pixelgroßer Divs. Der Wahnsinn nimmt seinen Lauf.

42voto

knut Punkte 679

Hinzu kommt, dass ich eine Diagrammanwendung entwickelt habe, die zunächst mit Canvas begann. Das Diagramm besteht aus vielen Knoten, und sie können ziemlich groß werden. Der Benutzer kann Elemente im Diagramm herumziehen.

Ich habe festgestellt, dass SVG auf meinem Mac für sehr große Bilder besser geeignet ist. Ich habe ein MacBook Pro 2013 13" Retina, und es läuft die Fiddle unten ganz gut. Das Bild ist 6000x6000 Pixel groß und hat 1000 Objekte. Ein ähnlicher Aufbau in Canvas war für mich unmöglich zu animieren, wenn der Benutzer Objekte im Diagramm herumzog.

Auf modernen Bildschirmen müssen Sie auch unterschiedliche Auflösungen berücksichtigen, und hier bietet Ihnen SVG all dies kostenlos.

Fiedel: http://jsfiddle.net/knutsi/PUcr8/16/

Vollbild: 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 1000 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);

28voto

Leo The Four Punkte 651

Die Kenntnis der Unterschiede zwischen SVG und Canvas ist bei der Auswahl des richtigen Formats hilfreich.

Segeltuch

SVG

  • Auflösung unabhängig
  • Unterstützung für Event-Handler
  • Am besten geeignet für Anwendungen mit großen Rendering-Bereichen (Google Maps)
  • Langsames Rendering, wenn es komplex ist (alles, was das DOM häufig verwendet, ist langsam)
  • Nicht für Spielanwendungen geeignet

23voto

Sebastian Punkte 7220

Auch wenn an den meisten der obigen Antworten noch etwas Wahres dran ist, denke ich, dass sie eine Aktualisierung verdienen:

Im Laufe der Jahre hat sich die Leistung von SVG stark verbessert, und jetzt gibt es Hardware-beschleunigte CSS-Übergänge und Animationen für SVG die überhaupt nicht von der JavaScript-Leistung abhängen. Natürlich hat sich auch die JavaScript-Leistung verbessert und damit auch die Leistung von Canvas, aber nicht so sehr wie die von SVG. Außerdem gibt es ein "neues Kind" auf dem Block, das heute in fast allen Browsern verfügbar ist, und das ist WebGL . Um die gleichen Worte zu verwenden, die Simon oben verwendet hat: Es übertrifft sowohl Canvas als auch SVG Hände weg. Das heißt aber nicht, dass sie die bevorzugte Technologie sein sollte, denn sie ist sehr schwer zu handhaben und nur in ganz bestimmten Anwendungsfällen schneller.

IMHO bietet SVG für die meisten Anwendungsfälle heute das beste Verhältnis zwischen Leistung und Nutzbarkeit. Visualisierungen müssen sehr komplex (in Bezug auf die Anzahl der Elemente) und gleichzeitig sehr einfach (pro Element) sein, damit Canvas und erst recht WebGL wirklich glänzen.

Unter diese Antwort auf eine ähnliche Frage Ich gebe weitere Einzelheiten an, warum ich denke, dass die Kombination von allen drei Technologien ist manchmal die beste Option, die Sie haben.

19voto

Ümit Punkte 17289

Ich stimme den Schlussfolgerungen von Simon Sarris zu:

Ich habe einige Visualisierungen in Protovis (SVG) mit Processingjs (Canvas) verglichen, die > 2000 Punkte anzeigen und Processingjs ist viel schneller als Protovis.

Die Handhabung von Ereignissen mit SVG ist natürlich viel einfacher, weil man sie an die Objekte anhängen kann. In Canvas müssen Sie es manuell tun (Mausposition überprüfen, etc.), aber für einfache Interaktion sollte es nicht schwer sein.

Außerdem gibt es die dojo.gfx Bibliothek des Dojo-Toolkits. Sie bietet eine Abstraktionsschicht und Sie können den Renderer (SVG, Canvas, Silverlight) angeben. Das könnte auch eine brauchbare Wahl sein, obwohl ich nicht weiß, wie viel Overhead die zusätzliche Abstraktionsschicht hinzufügt, aber es macht es einfach, Interaktionen und Animationen zu kodieren und ist Renderer-unabhängig.

Hier sind einige interessante Benchmarks:

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X