web-dev-qa-db-fra.com

Obtenez SVG de l'élément canvas et enregistrez-le

Actuellement, je crée une petite application pour un ami, qui commence son doctorat et a besoin de construire des graphiques de réseau. Jusqu'à présent, tout fonctionne bien en utilisant le graphique a Force Directed. Les nœuds des graphiques peuvent être déplacés pour styliser la disposition.

Ce que je n'arrive pas à comprendre, c'est:

"comment extraire les données du canevas et les sauvegarder dans un fichier SVG" .

Ce que j'ai essayé:

J'ai déjà essayé d'accéder aux données d'image à partir de la console avec

var app.canvas = document.getElementById( 'graph-canvas' )
    .getContext( '2d' )
        .getImageData( 0, 0, 200, 200 );

et a obtenu un (object) ImageData en retour. Maintenant, je peux accéder aux ↑ données de canevas affichées avec app.canvas.data. (Lorsque j'essaie de rechercher les valeurs, le navigateur commence à se bloquer et demande si le script doit être arrêté - Chrome & FF dernier).

Comment pourrais-je aller d'ici pour obtenir le SVG dessiné puis enregistré par le clic d'un bouton?

MODIFIER:

Jusqu'à présent, j'ai découvert comment dessiner le SVG et ajouter un image/png élément. Cependant, il ne s'affiche pas.

// Add the test SVG el:
var svg = document.createElementNS( "http://www.w3.org/2000/svg", "svg" );
svg.setAttribute( 'style', 'border: 1px solid black;' )
        .setAttribute( 'width', '600' )
        .setAttribute( 'height', '400' )
        .setAttributeNS(
            'http://www.w3.org/2000/xmlns/',
            'xmlns:xlink',
            'http://www.w3.org/1999/xlink'
        );

// Call
importCanvas( document.getElementById( 'infovis-canvas' ), svg ); 

// Function: Add data to SVG
function importCanvas( sourceCanvas, targetSVG ) 
{
    // get base64 encoded png data url from Canvas
    var img_dataurl = sourceCanvas.toDataURL( "image/png" );

    var svg_img = document.createElementNS(
        "http://www.w3.org/2000/svg",
        "image"
    );

    svg_img.setAttributeNS(
        'http://www.w3.org/1999/xlink',
        'xlink:href',
        img_dataurl
    );
    jQuery( targetSVG.appendChild( svg_img ) )
        .appendTo( '#graph-container' );

    console.log( 'done' ); // Log & confirm
}

Et enfin le ...

// ...resulting SVG element containing the image element
<svg style="border: 1px solid black;" width="600" height="400" xlink="http://www.w3.org/1999/xlink"><image href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABQAAA(...)

L'interface utilisateur fonctionne avec jQuery UI, jQuery et la bibliothèque The Jit/InfoVIZ , donc ceux-ci sont disponibles.

24
kaiser

Si vous souhaitez le conserver en tant que graphique vectoriel plutôt qu'en tant que raster, vous pouvez essayer l'une des bibliothèques qui traduisent les opérations de l'API Canvas en svg.

Pour SVGKit :

var svgkitContext = new SVGCanvas(150,150);

function draw(ctx) {
   // ... normal canvas drawing commands go here ...
}

// draw to SVGKit canvas (svg) instead of canvasElement.getContext("2d")
draw(svgkitContext);

Fonctionnement complet exemple de ce qui précède.

Pour canvas-svg :

var canvasSVGContext = new CanvasSVG.Deferred();
canvasSVGContext.wrapCanvas(document.querySelector("canvas"));
var canvasContext = document.querySelector("canvas").getContext("2d");

function draw(ctx) {
    // ... normal canvas drawing commands go here ...
}

// draw to html5 canvas and record as svg at the same time
draw(canvasContext);

// append the svg result
var svg = document.appendChild(canvasContext.getSVG());

Fonctionnement complet exemple de ce qui précède.

Pour générer des svg à la place:

Une autre option est bien sûr de faire le graphique en tant que svg en premier lieu, d3.js est une bibliothèque javascript qui le rend facile à faire, voir par exemple cet exemple d'un graphique dirigé par la force.

10
Erik Dahlström

Si vous êtes limité à ImageData, vous n'avez pas de chance, car ce n'est qu'un simple tableau de pixels (voir référence ). Vous ne pouvez pas obtenir une image SVG significative à partir de là. Vous pouvez probablement retirer une représentation .png ... mais c'est une image statique sans interaction.

Si vous allez faire une sorte de canevas pour l'exportation SVG, il est important de savoir comment vous faites le dessin du canevas. La meilleure approche serait d'utiliser une bibliothèque qui maintient un canevas graphique de scène .

Fabric.js semble être un bon choix. Vous pouvez faire le dessin avec canvas, puis appeler canvas.toSVG() et obtenir votre image svg.

6
mihai