Je souhaite convertir des fichiers SVG en images bitmap (telles que JPEG, PNG, etc.) via JavaScript.
Voici comment vous pouvez le faire via JavaScript:
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...
});
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;
}
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:
Ensuite, vous pouvez afficher une image avec le tag img:
<img src="data:image/png;base64, [base64 data]"/>
Cela fonctionne sur le navigateur.
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.
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/#
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()