web-dev-qa-db-fra.com

Convertissez SVG en image (JPEG, PNG, etc.) dans le navigateur

Je souhaite convertir des fichiers SVG en images bitmap (telles que JPEG, PNG, etc.) via JavaScript.

273
Zain

Voici comment vous pouvez le faire via JavaScript:

  1. Utilisez la bibliothèque JavaScript de canvg pour rendre l'image SVG à l'aide de Canvas: https://github.com/gabelerner/canvg
  2. Capturez un URI de données codé au format JPG (ou PNG) à partir du canevas, en respectant les instructions suivantes: Capture HTML Canvas au format gif/jpg/png/pdf?
232
jbeard4

la solution jbeard4 a fonctionné à merveille.

J'utilise Raphael SketchPad pour créer un fichier SVG. Lien vers les fichiers à l'étape 1.

Pour un bouton de sauvegarde (l'id de svg est "editor", l'id de canvas est "canvas"):

$("#editor_save").click(function() {

// the canvg call that takes the svg xml and converts it to a canvas
canvg('canvas', $("#editor").html());

// the canvas calls to output a png
var canvas = document.getElementById("canvas");
var img = canvas.toDataURL("image/png");
// do what you want with the base64, write to screen, post to server, etc...
});
43
coop

Cela semble fonctionner dans la plupart des navigateurs:

function copyStylesInline(destinationNode, sourceNode) {
   var containerElements = ["svg","g"];
   for (var cd = 0; cd < destinationNode.childNodes.length; cd++) {
       var child = destinationNode.childNodes[cd];
       if (containerElements.indexOf(child.tagName) != -1) {
            copyStylesInline(child, sourceNode.childNodes[cd]);
            continue;
       }
       var style = sourceNode.childNodes[cd].currentStyle || window.getComputedStyle(sourceNode.childNodes[cd]);
       if (style == "undefined" || style == null) continue;
       for (var st = 0; st < style.length; st++){
            child.style.setProperty(style[st], style.getPropertyValue(style[st]));
       }
   }
}

function triggerDownload (imgURI, fileName) {
  var evt = new MouseEvent("click", {
    view: window,
    bubbles: false,
    cancelable: true
  });
  var a = document.createElement("a");
  a.setAttribute("download", fileName);
  a.setAttribute("href", imgURI);
  a.setAttribute("target", '_blank');
  a.dispatchEvent(evt);
}

function downloadSvg(svg, fileName) {
  var copy = svg.cloneNode(true);
  copyStylesInline(copy, svg);
  var canvas = document.createElement("canvas");
  var bbox = svg.getBBox();
  canvas.width = bbox.width;
  canvas.height = bbox.height;
  var ctx = canvas.getContext("2d");
  ctx.clearRect(0, 0, bbox.width, bbox.height);
  var data = (new XMLSerializer()).serializeToString(copy);
  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);
    if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob)
    {
        var blob = canvas.msToBlob();         
        navigator.msSaveOrOpenBlob(blob, fileName);
    } 
    else {
        var imgURI = canvas
            .toDataURL("image/png")
            .replace("image/png", "image/octet-stream");
        triggerDownload(imgURI, fileName);
    }
    document.removeChild(canvas);
  };
  img.src = url;
}
12
worstenbrood

Voici une solution côté serveur basée sur PhantomJS. Vous pouvez utiliser JSONP pour effectuer un appel entre domaines au service d'imagerie:

https://github.com/vidalab/banquo-server

Par exemple:

http: // [hôte] /api/https%3A%2F%2Fvida.io%2Fdocuments%2FWgBMc4zDWF7YpqXGR/viewport_width=980&viewport_height=900&delay=5000&selector=%23canvas

Ensuite, vous pouvez afficher une image avec le tag img:

<img src="data:image/png;base64, [base64 data]"/>

Cela fonctionne sur le navigateur.

2
Phuoc Do

J'ai écrit cette classe ES6 qui fait le travail.

class SvgToPngConverter {
  constructor() {
    this._init = this._init.bind(this);
    this._cleanUp = this._cleanUp.bind(this);
    this.convertFromInput = this.convertFromInput.bind(this);
  }

  _init() {
    this.canvas = document.createElement("canvas");
    this.imgPreview = document.createElement("img");
    this.imgPreview.style = "position: absolute; top: -9999px";

    document.body.appendChild(this.imgPreview);
    this.canvasCtx = this.canvas.getContext("2d");
  }

  _cleanUp() {
    document.body.removeChild(this.imgPreview);
  }

  convertFromInput(input, callback) {
    this._init();
    let _this = this;
    this.imgPreview.onload = function() {
      const img = new Image();
      _this.canvas.width = _this.imgPreview.clientWidth;
      _this.canvas.height = _this.imgPreview.clientHeight;
      img.crossOrigin = "anonymous";
      img.src = _this.imgPreview.src;
      img.onload = function() {
        _this.canvasCtx.drawImage(img, 0, 0);
        let imgData = _this.canvas.toDataURL("image/png");
        if(typeof callback == "function"){
            callback(imgData)
        }
        _this._cleanUp();
      };
    };

    this.imgPreview.src = input;
  }
}

Voici comment vous l'utilisez

let input = "https://restcountries.eu/data/afg.svg"
new SvgToPngConverter().convertFromInput(input, function(imgData){
    // You now have your png data in base64 (imgData). 
    // Do what ever you wish with it here.
});

Si vous voulez une version JavaScript de Vanilla, vous pouvez aller sur le site de Babel et transcrire le code ici.

0
Cels

J'ai récemment découvert deux bibliothèques de traçage d'images pour JavaScript qui sont en mesure de créer une approximation acceptable du bitmap, à la fois en taille et en qualité. Je développe cette bibliothèque JavaScript et CLI:

https://www.npmjs.com/package/svg-png-converter

Qui fournit une API unifiée pour tous, supportant le navigateur et le nœud, ne dépendant pas de DOM, et un outil de ligne de commande.

Pour convertir des logos/dessins animés/comme des images, il fait un excellent travail. Pour les photos/réalisme, quelques ajustements sont nécessaires car la taille de la sortie peut augmenter considérablement.

Il a un terrain de jeu bien que je travaille actuellement sur un meilleur, plus facile à utiliser, car de nouvelles fonctionnalités ont été ajoutées:

https://cancerberosgx.github.io/demos/svg-png-converter/playground/#

0
cancerbero

changez svg pour correspondre à votre élément

function svg2img(){
    var svg = document.querySelector('svg');
    var xml = new XMLSerializer().serializeToString(svg);
    var svg64 = btoa(xml); //for utf8: btoa(unescape(encodeURIComponent(xml)))
    var b64start = 'data:image/svg+xml;base64,';
    var image64 = b64start + svg64;
    return image64;
};svg2img()
0
Mahdi Khalili