javascript - w3schools - svg html path




HTML5 Canvas vs. SVG vs. div (6)

Qual è l'approccio migliore per creare elementi al volo e poterli spostare? Ad esempio, supponiamo di voler creare un rettangolo, un cerchio e un poligono e quindi selezionare quegli oggetti e spostarli.

Comprendo che HTML5 fornisce tre elementi che possono renderlo possibile: svg , canvas e div . Per quello che voglio fare, quale di questi elementi fornirà le migliori prestazioni?

Per confrontare questi approcci, stavo pensando di creare tre pagine web visivamente identiche ognuna con un'intestazione, un piè di pagina, un widget e un contenuto di testo. Il widget nella prima pagina verrebbe creato interamente con l'elemento canvas , il secondo interamente con l'elemento svg e il terzo con l'elemento div plain, HTML e CSS.


La risposta breve:

SVG sarebbe più facile per te, dal momento che la selezione e lo spostamento è già integrato. Gli oggetti SVG sono oggetti DOM, quindi hanno gestori "click", ecc.

I DIV sono ok ma goffi e hanno un carico di prestazioni terribile a grandi numeri.

Canvas ha le migliori prestazioni a mani libere, ma devi implementare tutti i concetti di stato gestito (selezione di oggetti, ecc.) O utilizzare una libreria.

La lunga risposta:

HTML5 Canvas è semplicemente una superficie di disegno per una bitmap. Ti prepari a disegnare (diciamo con uno spessore di colore e linea), disegna quella cosa, e quindi la tela non ha conoscenza di quella cosa: non sa dove sia o cosa abbia disegnato, è solo pixel. Se vuoi disegnare rettangoli e farli spostare o essere selezionabili, devi codificare tutto da zero, incluso il codice per ricordare che li hai disegnati.

D'altra parte, SVG deve mantenere i riferimenti a ciascun oggetto che esegue il rendering. Ogni elemento SVG / VML che crei è un elemento reale nel DOM. Di default questo ti permette di tenere traccia molto migliore degli elementi che crei e rende più facile gestire cose del mouse come gli eventi del mouse, ma rallenta significativamente quando ci sono un gran numero di oggetti

Quei riferimenti SVG DOM significano che alcuni dei passi necessari per gestire le cose che disegni sono fatti per te. E SVG è più veloce nel rendering di oggetti molto grandi , ma più lento nel rendering di molti oggetti.

Un gioco sarebbe probabilmente più veloce in Canvas. Un enorme programma di mappe sarebbe probabilmente più veloce in SVG. Se vuoi usare Canvas, ho alcuni tutorial su come ottenere oggetti mobili attivi e funzionanti here .

La tela sarebbe meglio per cose più veloci e una pesante manipolazione di bitmap (come l'animazione), ma richiederà più codice se si desidera molta interattività.

Ho eseguito un sacco di numeri sul disegno HTML DIV-made rispetto al disegno su tela. Potrei fare un enorme post sui benefici di ciascuno, ma darò alcuni dei risultati rilevanti dei miei test da considerare per la tua specifica applicazione:

Ho realizzato pagine di prova DIV Canvas e HTML, entrambi con "nodi" mobili. I nodi Canvas erano oggetti che ho creato e tenuto traccia di in Javascript. I nodi HTML erano Divs mobili.

Ho aggiunto 100.000 nodi a ciascuno dei miei due test. Hanno eseguito in modo diverso:

La scheda del test HTML è stata caricata per sempre (con un tempo leggermente inferiore ai 5 minuti, chrome ha chiesto di chiudere la pagina la prima volta). Il task manager di Chrome afferma che la scheda occupa 168 MB. Quando lo guardo, occupa il 12-13% della CPU, lo 0% quando non guardo.

La scheda Canvas è caricata in un secondo e occupa 30 MB. Inoltre, occupa il 13% del tempo di CPU tutto il tempo, indipendentemente dal fatto che lo si guardi o meno. (Modifica del 2013: per lo più hanno risolto il problema)

Il trascinamento nella pagina HTML è più agevole, come previsto dal progetto, poiché l'attuale configurazione prevede di ridisegnare TUTTO ogni 30 millisecondi nel test Canvas. Ci sono molte ottimizzazioni da fare per Canvas per questo. (l'invalidazione della tela è la più semplice, anche le regioni di ritaglio, il ridisegno selettivo, ecc. dipende solo da quanto hai voglia di implementare)

Non c'è dubbio che è possibile ottenere Canvas per essere più veloce nella manipolazione degli oggetti come i div in quel semplice test, e ovviamente molto più veloce nel tempo di caricamento. Disegnare / caricare è più veloce in Canvas e ha molto più spazio per le ottimizzazioni (ad esempio, escludere le cose fuori dallo schermo è molto semplice).

Conclusione:

  • SVG è probabilmente migliore per applicazioni e app con pochi elementi (meno di 1000? Dipende davvero)
  • La tela è migliore per migliaia di oggetti e un'attenta manipolazione, ma è necessario molto più codice (o una libreria) per farlo decollare.
  • Gli HTML Div sono goffi e non si scalano, rendendo possibile un cerchio con angoli arrotondati, rendendo possibili forme complesse ma coinvolgendo centinaia di piccoli minuscoli div al pixel. Segue la follia.

Conoscere le differenze tra SVG e Canvas sarebbe utile per selezionare quello giusto.

Tela

  • Risoluzione dipendente
  • Nessun supporto per i gestori di eventi
  • Scarse capacità di rendering del testo
  • È possibile salvare l'immagine risultante come .png o .jpg
  • Adatto per giochi con grafica intensiva

SVG

  • Risoluzione indipendente
  • Supporto per gestori di eventi
  • Ideale per applicazioni con aree di rendering di grandi dimensioni (Google Maps)
  • Rendering lento se complesso (tutto ciò che usa molto il DOM sarà lento)
  • Non adatto per l'applicazione di gioco

Mentre su Google trovo una buona spiegazione sull'uso e la compressione di SVG e Canvas su http://teropa.info/blog/2016/12/12/graphics-in-angular-2.html

Spero che sia d'aiuto:

  • SVG, come HTML, usa il rendering mantenuto : quando vogliamo disegnare un rettangolo sullo schermo, utilizziamo in modo dichiarativo un elemento nel nostro DOM. Il browser quindi disegnerà un rettangolo, ma creerà anche un oggetto SVGRectElement memoria che rappresenta il rettangolo. Questo oggetto è qualcosa che si attacca a noi per manipolare - è mantenuto. Possiamo assegnare diverse posizioni e dimensioni ad esso nel tempo. Possiamo anche allegare listener di eventi per renderlo interattivo.
  • La tela usa il rendering immediato : quando disegniamo un rettangolo , il browser rende immediatamente un rettangolo sullo schermo, ma non ci sarà mai alcun "oggetto rettangolo" che lo rappresenta. C'è solo un mucchio di pixel nel buffer della tela. Non possiamo spostare il rettangolo. Possiamo solo disegnare un altro rettangolo. Non possiamo rispondere ai clic o ad altri eventi sul rettangolo. Possiamo solo rispondere agli eventi su tutta la tela .

Quindi canvas è un'API restrittiva di livello più basso rispetto a SVG. Ma c'è un rovescio della medaglia, che è che con la tela puoi fare di più con la stessa quantità di risorse. Poiché il browser non deve creare e mantenere il grafo degli oggetti in memoria di tutte le cose che abbiamo disegnato, ha bisogno di meno risorse di memoria e calcolo per disegnare la stessa scena visiva. Se hai una visualizzazione molto grande e complessa da disegnare, Canvas potrebbe essere il tuo biglietto.


Per aggiungere a questo, ho fatto un'applicazione di diagrammi e inizialmente ho iniziato con la tela. Il diagramma consiste di molti nodi e possono diventare abbastanza grandi. L'utente può trascinare elementi nel diagramma.

Quello che ho trovato è che sul mio Mac, per immagini molto grandi, SVG è superiore. Ho un MacBook Pro 2013 13 "Retina, e gira abbastanza bene il violino, l'immagine è di 6000x6000 pixel e ha 1000 oggetti. Una simile costruzione in tela era impossibile da animare per me quando l'utente trascinava oggetti nel diagramma.

Su schermi moderni devi anche tenere conto di diverse risoluzioni, e qui SVG ti offre tutto ciò gratuitamente.

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

Schermo intero: 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);

Solo i miei 2 centesimi per quanto riguarda l'opzione div.

Famous / Infamous e SamsaraJS (e forse altri) usano div non annidati in posizione assoluta (con contenuto HTML / CSS non banale), combinati con matrix2d / matrix3d ​​per il posizionamento e le trasformazioni 2D / 3D, e raggiungono un 60FPS stabile su hardware mobile moderato , quindi discuterei contro i div che sono un'opzione lenta.

Ci sono un sacco di registrazioni dello schermo su Youtube e altrove, roba 2D / 3D ad alte prestazioni in esecuzione nel browser con tutto ciò che è un elemento DOM che puoi controllare su Element , a 60FPS (mescolato con WebGL per determinati effetti, ma non per il parte principale del rendering).


Sono d'accordo con le conclusioni di Simon Sarris:

Ho confrontato alcune visualizzazioni di Protovis (SVG) con Processingjs (Canvas) che mostrano> 2000 punti e processingjs è molto più veloce di protovis.

La gestione degli eventi con SVG è ovviamente molto più semplice perché è possibile collegarli agli oggetti. In Canvas devi farlo manualmente (controlla la posizione del mouse, ecc.) Ma per una semplice interazione non dovrebbe essere difficile.

Esiste anche la libreria dojo.gfx del toolkit dojo. Fornisce un livello di astrazione ed è possibile specificare il renderer (SVG, Canvas, Silverlight). Potrebbe anche essere una scelta valida anche se non so quanto sovraccarico aggiunga il livello aggiuntivo di astrazione, ma rende facile codificare interazioni e animazioni ed è indipendente dal renderer.

Ecco alcuni punti di riferimento interessanti:





html5-canvas