web-dev-qa-db-fra.com

Enregistrer le SVG en ligne au format JPEG / PNG / SVG

J'ai un SVG en ligne dans mon html, et je dois être en mesure de l'enregistrer au format JPEG, PNG ou SVG.

J'ai essayé plusieurs méthodes différentes pour convertir le SVG en canevas, puis en JPEG, mais je n'ai pas réussi à les faire fonctionner.

Voici un exemple de mon SVG en ligne.

.font {
        color: #ffffff;
        font-family: Roboto;
        font-weight: bold;
        text-transform: uppercase;
}
.name {
        font-size: 64pt;
}
.top-bar-text {
        font-size: 32pt;
}
.font tspan {
        dominant-baseline: middle;
}
<link href='http://fonts.googleapis.com/css?family=Roboto:700' rel='stylesheet' type='text/css'>

<svg width="256" height="256" id="icon">
  <rect class="bg1" id="bg_color_1" x="0" y="0" width="256" height="256" fill="#4cbc5a" />
  <path class="bg2" id="bg_color_2" d="M 0 96 L0,256 L256,256 L256,96 s -128 96 -256 0" fill="#08a21c" />
  <text id="left_corner_text" x="24" y="36" width="48" height="64" class="top_bar lct font top-bar-text" text-anchor="middle" fill="#ffffff"><tspan>1</tspan></text>
  <text id="right_corner_text" x="232" y="36" width="48" height="64" class="top_bar rct font top-bar-text" text-anchor="middle" fill="#ffffff"><tspan>2</tspan></text>
  <text id="line_1_text" transform="scale(1,2)" x="128" y="90" width="256" height="192" class="l1t font name" text-anchor="middle" fill="#ffffff"><tspan>ABC</tspan></text>
</svg>

De plus, tous les éléments ne doivent pas être exportés, car certaines des options dont dispose l'utilisateur sont de supprimer les numéros de coin supérieurs.

Je voudrais quand il a été converti pour télécharger directement sur le navigateur.

29
Tim Rideyourbike

De nos jours, c'est assez simple.

L'idée de base est:

  1. svg sur toile
  2. canvas à dataUrl
  3. déclencher le téléchargement depuis dataUrl

cela fonctionne réellement en dehors de l'extrait de stackoverflow

var btn = document.querySelector('button');
var svg = document.querySelector('svg');
var canvas = document.querySelector('canvas');

function triggerDownload (imgURI) {
  var evt = new MouseEvent('click', {
    view: window,
    bubbles: false,
    cancelable: true
  });

  var a = document.createElement('a');
  a.setAttribute('download', 'MY_COOL_IMAGE.png');
  a.setAttribute('href', imgURI);
  a.setAttribute('target', '_blank');

  a.dispatchEvent(evt);
}

btn.addEventListener('click', function () {
  var canvas = document.getElementById('canvas');
  var ctx = canvas.getContext('2d');
  var data = (new XMLSerializer()).serializeToString(svg);
  var DOMURL = window.URL || window.webkitURL || window;

  var img = new Image();
  var svgBlob = new Blob([data], {type: 'image/svg+xml;charset=utf-8'});
  var url = DOMURL.createObjectURL(svgBlob);

  img.onload = function () {
    ctx.drawImage(img, 0, 0);
    DOMURL.revokeObjectURL(url);

    var imgURI = canvas
        .toDataURL('image/png')
        .replace('image/png', 'image/octet-stream');

    triggerDownload(imgURI);
  };

  img.src = url;
});
<button>svg to png</button>

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="200" height="200">
  <rect x="10" y="10" width="50" height="50" />
  <text x="0" y="100">Look, i'm cool</text>
</svg>

<canvas id="canvas"></canvas>

En ce qui concerne la partie téléchargement, vous pouvez configurer un nom de fichier et etc etc (mais pas dans cet exemple). Il y a quelques jours, j'ai répondu à une question sur la façon de télécharger une partie spécifique de HTML à partir de la page donnée. Il pourrait être utile concernant la partie téléchargement: https://stackoverflow.com/a/28087280/217818

mise à jour : vous permet maintenant de spécifier le nom du fichier

53
Ciro Costa

Voici une solution qui fonctionne également dans IE11.

Je viens de faire un tas de tests de diverses méthodes et bien que la réponse ci-dessus de Ciro Costa soit fantastique en ce qu'elle fonctionne dans Firefox et Chrome cela ne fonctionne pas dans IE11. IE11 échoue en raison d'un problème de sécurité avec le rendu d'un svg sur le canevas qui nécessite une implémentation du canevas, canvg . Voici une solution utilisant canvg qui est assez concise et fonctionne dans la dernière version versions de Chrome, Firefox, Edge et IE11.

Violon: https://jsfiddle.net/StefanValentin/9mudw0ts/

[~ # ~] dom [~ # ~]

<svg
  id="my-svg"
  xmlns="http://www.w3.org/2000/svg"
  xmlns:xlink="http://www.w3.org/1999/xlink"
  version="1.1"
  width="200"
  height="200"
>
  <rect x="10" y="10" width="50" height="50" />
  <text x="0" y="100">Look, i'm cool</text>
</svg>

JavaScript

var svg = document.querySelector('#my-svg');
var data = (new XMLSerializer()).serializeToString(svg);
// We can just create a canvas element inline so you don't even need one on the DOM. Cool!
var canvas = document.createElement('canvas');
canvg(canvas, data, {
  renderCallback: function() {
    canvas.toBlob(function(blob) {
        download('MyImageName.png', blob);
    });
  }
});

La fonction download ci-dessus pourrait être ce que vous voulez faire, car il existe de nombreuses façons de déclencher un téléchargement via JavaScript. Voici celui que nous utilisons et qui fonctionne dans tous les navigateurs que j'ai testés.

// Initiate download of blob
function download(
  filename, // string
  blob // Blob
) {
  if (window.navigator.msSaveOrOpenBlob) {
    window.navigator.msSaveBlob(blob, filename);
  } else {
    const elem = window.document.createElement('a');
    elem.href = window.URL.createObjectURL(blob);
    elem.download = filename;
    document.body.appendChild(elem);
    elem.click();
    document.body.removeChild(elem);
  }
}
1
KhalilRavanna

Travailler sur @CiroCosta. 1 option si vous avez du mal à exporter un élément, vous pouvez simplement dessiner l'image sur la toile avant de dessiner l'image svg

    btn.addEventListener('click', function () {
      var canvas = document.getElementById('canvas');
      var ctx = canvas.getContext('2d');
      var data = (new XMLSerializer()).serializeToString(svg);
      var DOMURL = window.URL || window.webkitURL || window;

// get the raw image from the DOM
      var rawImage = document.getElementById('yourimageID');
      var img = new Image();
      var svgBlob = new Blob([data], {type: 'image/svg+xml;charset=utf-8'});
      var url = DOMURL.createObjectURL(svgBlob);

      img.onload = function () {

        ctx.drawImage(rawImage, 0, 0);
        ctx.drawImage(img, 0, 0);
        DOMURL.revokeObjectURL(url);

        var imgURI = canvas
            .toDataURL('image/png')
            .replace('image/png', 'image/octet-stream');

        triggerDownload(imgURI);
      };

      img.src = url;
    });

A fonctionné pour moi mais uniquement pour png et jpeg. Les fichiers SVG affichent toujours uniquement les éléments en ligne et non les balises

EDIT: La façon dont vous créez un svg comme celui-ci est en fait en convertissant la balise d'image en Base64 et le paramètre qui en tant que xlink: href dans les attributs d'image comme ceci:

<image id="crop" width="725" height="1764" xlink:href="data:image/png;base64,iVBORw0KGgo ... " />

puis déclencher le téléchargement sur l'url svg entière comme ceci:

btn.addEventListener('click', function () {
      var canvas = document.getElementById('canvas');
      var ctx = canvas.getContext('2d');
      var data = (new XMLSerializer()).serializeToString(svg);
      var DOMURL = window.URL || window.webkitURL || window;

      var rawImage = document.getElementById('yourimageID');
      var img = new Image();
      var svgBlob = new Blob([data], {type: 'image/svg+xml;charset=utf-8'});
      var url = DOMURL.createObjectURL(svgBlob);

      img.onload = function () {

       ctx.drawImage(img, 0, 0);


       triggerDownload(url);
       DOMURL.revokeObjectURL(url);
      }
};

vous pouvez convertir des pngs comme ceci ici :

function getDataUri(url, callback) {
            var image = new Image();

            image.onload = function () {
                var canvas = document.createElement('canvas');
                canvas.width = this.naturalWidth; // or 'width' if you want a special/scaled size
                canvas.height = this.naturalHeight; // or 'height' if you want a special/scaled size

                canvas.getContext('2d').drawImage(this, 0, 0);

                // Get raw image data
                callback(canvas.toDataURL('image/png').replace(/^data:image\/(png|jpg);base64,/, ''));

                // ... or get as Data URI
                callback(canvas.toDataURL('image/png'));
            };

            image.src = url;
        }

puis en définissant l'attribut

getDataUri('localImagepath', function(dataUri) {
       image.setAttribute('xlink:href',dataUri);
});
0
Chadd Frasier