web-dev-qa-db-fra.com

Comment dessiner un svg en ligne (dans DOM) sur un canevas?

Eh bien, j'ai besoin d'aide pour convertir un fichier/image .svg en fichier/image .png ...

J'ai une image .svg affichée sur ma page. Il est enregistré sur mon serveur (sous forme de fichier .png). Je dois le convertir en fichier .png à la demande (en cliquant sur un bouton) et enregistrer le fichier .png sur le serveur (je le ferai avec une demande .ajax).

Mais le problème est la conversion.

J'ai lu beaucoup de choses sur le Canvas html5, ce qui peut probablement aider à faire ce que je dois faire maintenant, mais je ne trouve pas de solution claire à mon problème, et, tbh, je ne comprends pas tout ce que j'ai trouvé ... Alors j'ai besoin de conseils/d'aide clairs sur la façon dont je dois le faire.

Voici le modèle "idée html":

<html>
    <body>
        <svg id="mySvg" width="300px" height="300px">
            <!-- my svg data -->
        </svg>
        <label id="button">Click to convert</label>
        <canvas id="myCanvas"></canvas>
    </body>
</html>

et quelques js:

<script>
    $("body").on("click","#button",function(){
        var svgText = $("#myViewer").outerHTML;
        var myCanvas = document.getElementById("canvas");
        var ctxt = myCanvas.getContext("2d");
    });
</script>

Ensuite, je dois dessiner le svg dans le Canvas, récupérer les données base64 et les enregistrer dans un fichier .png sur mon serveur ... mais ... comment? J'ai lu tellement de solutions différentes que je suis en fait ... perdu ... Je travaille sur un jsfiddle, mais je ne suis en fait ... nulle part ... http://jsfiddle.net/xfh7nctk/6 / ... Merci pour la lecture/aide

27
Julo0sS

Pour le SVG en ligne, vous devrez:

  • Convertissez la chaîne SVG en Blob
  • Obtenez une URL pour le blob
  • Créez un élément d'image et définissez l'URL comme src
  • Une fois chargé (onload) vous pouvez dessiner le SVG comme une image sur toile
  • Utilisez toDataURL() pour obtenir le fichier PNG à partir du canevas.

Par exemple:

function drawInlineSVG(ctx, rawSVG, callback) {

    var svg = new Blob([rawSVG], {type:"image/svg+xml;charset=utf-8"}),
        domURL = self.URL || self.webkitURL || self,
        url = domURL.createObjectURL(svg),
        img = new Image;

    img.onload = function () {
        ctx.drawImage(this, 0, 0);     
        domURL.revokeObjectURL(url);
        callback(this);
    };

    img.src = url;
}

// usage:
drawInlineSVG(ctxt, svgText, function() {
    console.log(canvas.toDataURL());  // -> PNG data-uri
});

Bien sûr, console.log ici n'est qu'un exemple. Stockez/transférez la chaîne à la place ici. (Je recommanderais également d'ajouter un gestionnaire onerror à l'intérieur de la méthode).

N'oubliez pas non plus de définir la taille du canevas à l'aide des attributs width et height, ou à partir de JavaScript à l'aide des propriétés.

42
user1693593

J'arrive longtemps après car une autre question a été soulevée à partir de celle-ci car la réponse acceptée peut produire un comportement indésirable.

La solution @ K3N a presque raison, mais je suis contre l'utilisation de svgElement.outerHTML.
Au lieu de cela, on devrait préférer new XMLSerializer().serializeToString(svgElement) .

De plus, l'utilisation de blob et de l'API URL n'est pas nécessaire et un simple dataURI a plus de compatibilité entre les navigateurs.

Donc, une version complète de ceci serait:

function drawInlineSVG(svgElement, ctx, callback){
  var svgURL = new XMLSerializer().serializeToString(svgElement);
  var img  = new Image();
  img.onload = function(){
    ctx.drawImage(this, 0,0);
    callback();
    }
  img.src = 'data:image/svg+xml; charset=utf8, '+encodeURIComponent(svgURL);
  }

//usage :
drawInlineSVG(document.querySelector('svg'), ctxt, function(){console.log(canvas.toDataURL())})
27
Kaiido