it-swarm.com.de

HTML5 Canvas vs. SVG vs. div

Was ist der beste Ansatz, um Elemente im Handumdrehen zu erstellen und sie bewegen zu können? Angenommen, ich möchte ein Rechteck, einen Kreis und ein Polygon erstellen, diese Objekte auswählen und verschieben.

Ich verstehe, dass HTML5 drei Elemente enthält, die dies ermöglichen können: svg , canvas und div . Für was ich tun möchte, welches dieser Elemente bietet die beste Leistung?

Um diese Ansätze zu vergleichen, überlegte ich, drei visuell identische Webseiten zu erstellen, die jeweils Kopf-, Fuß-, Widget- und Textinhalte enthalten. Das Widget auf der ersten Seite würde vollständig mit dem canvas -Element erstellt, das zweite vollständig mit dem svg -Element und das dritte mit dem einfachen div -Element, HTML und CSS .

442
verdy

Die kurze Antwort:

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

DIVs sind in Ordnung, aber klobig und haben schrecklich Leistungsbelastung bei großen Zahlen.

Canvas bietet zweifellos die beste Leistung, Sie müssen jedoch alle Konzepte des verwalteten Status (Objektauswahl usw.) selbst implementieren oder eine Bibliothek verwenden.


Die lange Antwort:

HTML5 Canvas ist einfach eine Zeichenfläche für eine Bitmap. Sie richten ein, um zu zeichnen (sagen Sie mit einer Farbe und einer Linienstärke), das Ding zu zeichnen, und dann hat der Canvas keine Kenntnis davon: Er weiß nicht, wo es ist oder was es ist, das Sie gerade gezeichnet haben, es ist nur Pixel. Wenn Sie Rechtecke zeichnen und sie bewegen oder auswählbar machen möchten, müssen Sie all das von Grund auf neu codieren , einschließlich des Codes, um sich daran zu erinnern, dass Sie zog sie.

SVG hingegen muss Verweise auf jedes Objekt pflegen, das es rendert. Jedes SVG/VML-Element, das Sie erstellen, ist ein echtes Element im DOM. Standardmäßig können Sie auf diese Weise die von Ihnen erstellten Elemente besser verfolgen und beispielsweise Mausereignisse einfacher verarbeiten. Dies wird jedoch erheblich verlangsamt, wenn eine große Anzahl von Objekten vorhanden ist

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

Ein Spiel wäre in Canvas wahrscheinlich schneller. Ein riesiges Kartenprogramm wäre in SVG wahrscheinlich schneller. Wenn Sie Canvas verwenden möchten, habe ich einige Tutorials, um bewegliche Objekte zum Laufen zu bringen hier .

Canvas ist besser für schnellere Aufgaben und umfangreiche Bitmap-Manipulationen (wie Animationen), benötigt jedoch mehr Code, wenn Sie viel Interaktivität wünschen.

Ich habe eine Reihe von Zahlen für HTML-DIV-Zeichnungen im Vergleich zu Canvas-Zeichnungen erstellt. Ich könnte einen großen Beitrag zu den Vorteilen der einzelnen Tests verfassen, aber ich werde einige der relevanten Ergebnisse meiner Tests für Ihre spezifische Anwendung 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 jedem meiner beiden Tests 100.000 Knoten hinzugefügt. Sie verhielten sich ganz anders:

Das Laden des HTML-Test-Tabs hat eine Ewigkeit gedauert (etwas weniger als 5 Minuten, chrome bat, die Seite beim ersten Mal abzubrechen). Der Task-Manager von Chrome gibt an, dass der Tab 168 MB belegt 12-13% CPU-Zeit, wenn ich es betrachte, 0%, wenn ich nicht schaue.

Die Canvas-Registerkarte wird in einer Sekunde geladen und nimmt 30 MB ein. Es beansprucht auch immer 13% der CPU-Zeit, unabhängig davon, ob man es sich ansieht oder nicht. (2013 edit: Das haben sie meistens behoben)

Das Ziehen auf der HTML-Seite ist reibungsloser, was vom Design erwartet wird, da das aktuelle Setup ALLES alle 30 Millisekunden im Canvas-Test neu zeichnen soll. Hierfür gibt es viele Optimierungen für Canvas. (Canvas-Invalidierung ist am einfachsten, auch das Ausschneiden von Regionen, selektives Neuzeichnen usw. hängt nur davon ab, wie sehr Sie die Implementierung bevorzugen.)

Es besteht kein Zweifel, dass Canvas bei der Objektmanipulation schneller sein kann als die divs in diesem einfachen Test und natürlich viel schneller in der Ladezeit. Das Zeichnen/Laden ist in Canvas schneller und bietet auch viel mehr Optimierungsmöglichkeiten (dh das Ausschließen von Objekten, die nicht auf dem Bildschirm angezeigt werden, ist sehr einfach).

Fazit:

  • SVG ist wahrscheinlich besser für Anwendungen und Apps mit wenigen Elementen (weniger als 1000? Hängt wirklich ab)
  • Canvas ist besser für Tausende von Objekten und sorgfältige Bearbeitung, aber es wird viel mehr Code (oder eine Bibliothek) benötigt, um es auf den Weg zu bringen.
  • HTML-Divs sind klobig und nicht skalierbar. Das Erstellen eines Kreises ist nur mit abgerundeten Ecken möglich. Das Erstellen komplexer Formen ist möglich, umfasst jedoch Hunderte winziger, pixelbreiter Divs. Wahnsinn folgt.
535
Simon Sarris

Dazu habe ich eine Diagrammanwendung erstellt und anfangs mit Canvas begonnen. Das Diagramm besteht aus vielen Knoten, die sehr groß werden können. Der Benutzer kann Elemente im Diagramm verschieben.

Was ich fand, war, dass SVG auf meinem Mac für sehr große Bilder überlegen ist. Ich habe ein MacBook Pro 2013 13 "Retina, und es läuft die Geige unten ziemlich gut. Das Bild ist 6000x6000 Pixel und hat 1000 Objekte. Eine ähnliche Konstruktion in Leinwand war für mich unmöglich zu animieren, als der Benutzer Objekte in der Maus herumzog Diagramm.

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

Fiddle: 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);
38
knut

Wenn Sie die Unterschiede zwischen SVG und Canvas kennen, können Sie die richtige auswählen.

Segeltuch

SVG

  • Auflösung unabhängig
  • Unterstützung für Eventhandler
  • Bestens geeignet für Anwendungen mit großen Renderflächen (Google Maps)
  • Langsames Rendern, wenn es komplex ist (alles, was das DOM häufig verwendet, ist langsam)
  • Nicht für Spieleanwendungen geeignet
22
Leo The Four

Ich stimme den Schlussfolgerungen von Simon Sarris zu:

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

Die Behandlung von Ereignissen mit SVG ist natürlich viel einfacher, da Sie sie an die Objekte anhängen können. In Canvas müssen Sie dies manuell tun (Mausposition überprüfen usw.), aber für eine einfache Interaktion sollte es nicht schwierig sein.

Es gibt auch die dojo.gfx Bibliothek des Dojo-Toolkits. Es bietet eine Abstraktionsebene und Sie können den Renderer (SVG, Canvas, Silverlight) angeben. Das könnte auch eine sinnvolle Wahl sein, obwohl ich nicht weiß, wie viel Overhead die zusätzliche Abstraktionsebene verursacht, aber es erleichtert das Codieren von Interaktionen und Animationen und ist rendererunabhängig.

Hier sind einige interessante Benchmarks:

18
Ümit

Nur meine 2 Cent in Bezug auf die Option divs.

Famous/Infamous und SamsaraJS (und möglicherweise andere) verwenden absolut positionierte, nicht verschachtelte Divs (mit nicht trivialem HTML/CSS-Inhalt), kombiniert mit matrix2d/matrix3d ​​für Positionierungs- und 2D/3D-Transformationen, und erzielen auf moderater mobiler Hardware stabile 60 fps Ich würde also dagegen argumentieren, dass Divs eine langsame Option sind.

Es gibt viele Bildschirmaufnahmen auf Youtube und anderswo, von hochleistungsfähigem 2D/3D-Material, das im Browser ausgeführt wird, wobei alles ein DOM-Element ist, das Sie Inspect Element einschalten können, bei 60 FPS (gemischt mit WebGL für bestimmte Effekte, aber nicht für den Hauptteil des Renderings).

16
Erik Allik

Obwohl die meisten der obigen Antworten noch zutreffend sind, sollten sie meines Erachtens aktualisiert werden:

Im Laufe der Jahre hat sich die Leistung von SVG erheblich verbessert, und jetzt gibt es hardwarebeschleunigte CSS-Übergänge und -Animationen für SVG , die nicht von der JavaScript-Leistung abhängen alle. Natürlich hat sich auch die JavaScript-Leistung und damit die Leistung von Canvas verbessert, aber nicht so sehr wie bei SVG. Es gibt auch ein "neues Kind" auf dem Block, das heutzutage in fast allen Browsern verfügbar ist, und das ist WebGL . Um die gleichen Wörter zu verwenden, die Simon oben verwendet hat: Es schlägt sowohl Canvas als auch SVG zweifellos. Dies bedeutet jedoch nicht, dass es sich um die erste Technologie handeln sollte, da die Arbeit mit dieser Technologie eine Herausforderung darstellt und sie nur in bestimmten Anwendungsfällen schneller ist.

Für die meisten heutigen Anwendungsfälle bietet SVG das beste Verhältnis von Leistung und Benutzerfreundlichkeit. Visualisierungen müssen sehr komplex (in Bezug auf die Anzahl der Elemente) und gleichzeitig sehr einfach (pro Element) sein, damit Canvas und vor allem WebGL wirklich glänzen.

In diese Antwort auf eine ähnliche Frage Ich gebe mehr Details an, warum ich denke, dass die Kombination aller drei Technologien manchmal ist die beste Option, die Sie haben.

14
Sebastian

Für Ihre Zwecke empfehle ich die Verwendung von SVG, da Sie DOM-Ereignisse, wie die Maushandhabung, einschließlich Drag & Drop, erhalten, kein eigenes Redraw implementieren und den Status von nicht nachverfolgen müssen Ihre Objekte. Verwenden Sie Canvas, wenn Sie Bitmap-Bilder bearbeiten müssen, und verwenden Sie ein reguläres div, wenn Sie in HTML erstellte Inhalte bearbeiten möchten. In Bezug auf die Leistung werden Sie feststellen, dass moderne Browser jetzt alle drei beschleunigen, dass Canvas jedoch bisher die meiste Aufmerksamkeit erhalten hat. Auf der anderen Seite ist es entscheidend, wie gut Sie Ihr Javascript schreiben, um die bestmögliche Leistung mit Canvas zu erzielen. Daher würde ich weiterhin die Verwendung von SVG empfehlen.

13
Gaurav

Beim googeln finde ich eine gute Erklärung zur Verwendung und Komprimierung von [~ # ~] svg [~ # ~] und Canvas unter http://teropa.info/blog/2016/12/12/graphics-in-angular-2.html

Ich hoffe es hilft:

  • SVG verwendet wie HTML beibehaltenes Rendering : Wenn wir ein Rechteck auf dem Bildschirm zeichnen möchten, verwenden wir deklarativ ein Element in unserem DOM. Der Browser zeichnet dann ein Rechteck, erstellt aber auch ein speicherinternes SVGRectElement Objekt, das das Rechteck darstellt. Dieses Objekt ist etwas, das wir manipulieren können - es bleibt erhalten. Wir können ihm im Laufe der Zeit verschiedene Positionen und Größen zuweisen. Wir können auch Ereignis-Listener hinzufügen, um es interaktiv zu gestalten.
  • Canvas verwendet sofortiges Rendern : Wenn wir ein Rechteck zeichnen , rendert der Browser sofort ein Rechteck auf dem Bildschirm, aber es gibt nie wird jedes "Rechteckobjekt" sein, das es repräsentiert. Der Canvas-Puffer enthält nur ein paar Pixel. Wir können das Rechteck nicht verschieben. Wir können nur ein anderes Rechteck zeichnen. Wir können nicht auf Klicks oder andere Ereignisse im Rechteck reagieren. Wir können nur auf Ereignisse auf der gesamten Zeichenfläche reagieren.

Canvas ist also eine einfachere, restriktivere API als SVG. Aber das hat eine Kehrseite: Mit Canvas können Sie mit der gleichen Menge an Ressourcen mehr erreichen. Da der Browser nicht das speicherinterne Objektdiagramm aller von uns gezeichneten Objekte erstellen und verwalten muss, benötigt er weniger Speicher und Rechenressourcen, um dieselbe visuelle Szene zu zeichnen. Wenn Sie eine sehr große und komplexe Visualisierung zeichnen müssen, ist Canvas möglicherweise Ihr Ticket.

2
Alireza Fattahi