Quiero convertir SVG en imágenes de mapa de bits (como JPEG, PNG, etc.) a través de JavaScript.
Quiero convertir SVG en imágenes de mapa de bits (como JPEG, PNG, etc.) a través de JavaScript.
Respuestas:
Así es como puedes hacerlo a través de JavaScript:
toImage()
y también download()
para una imagen descargada automáticamente.
La solución jbeard4 funcionó a la perfección.
Estoy usando Raphael SketchPad para crear un SVG. Enlace a los archivos en el paso 1.
Para un botón Guardar (la identificación de svg es "editor", la identificación del lienzo es "lienzo"):
$("#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...
});
<svg>...</svg
pero la función jquery html () no agrega la etiqueta svg, por lo que este código funciona para mí, pero necesitaba editar canvg livecanvg('canvas', '<svg>'+$("#editor").html()+'</svg>');
$(selector).html()
al padre de tu elemento svg , funcionará
html()
en envoltorios, o construir manualmente la svg
etiqueta principal , que incluso podría tener atributos que omita con este truco. Solo use $(svg_elem)[0].outerHTML
le da la fuente completa de la svg y su contenido. Solo digo ...
Esto parece funcionar en la mayoría de los navegadores:
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;
}
.msToBlob()
La solución para convertir SVG a blob URL y blob URL a imagen png
const svg=`<svg version="1.1" baseProfile="full" width="300" height="200"
xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" fill="red" />
<circle cx="150" cy="100" r="80" fill="green" />
<text x="150" y="125" font-size="60" text-anchor="middle" fill="white">SVG</text></svg>`
svgToPng(svg,(imgData)=>{
const pngImage = document.createElement('img');
document.body.appendChild(pngImage);
pngImage.src=imgData;
});
function svgToPng(svg, callback) {
const url = getSvgUrl(svg);
svgUrlToPng(url, (imgData) => {
callback(imgData);
URL.revokeObjectURL(url);
});
}
function getSvgUrl(svg) {
return URL.createObjectURL(new Blob([svg], { type: 'image/svg+xml' }));
}
function svgUrlToPng(svgUrl, callback) {
const svgImage = document.createElement('img');
// imgPreview.style.position = 'absolute';
// imgPreview.style.top = '-9999px';
document.body.appendChild(svgImage);
svgImage.onload = function () {
const canvas = document.createElement('canvas');
canvas.width = svgImage.clientWidth;
canvas.height = svgImage.clientHeight;
const canvasCtx = canvas.getContext('2d');
canvasCtx.drawImage(svgImage, 0, 0);
const imgData = canvas.toDataURL('image/png');
callback(imgData);
// document.body.removeChild(imgPreview);
};
svgImage.src = svgUrl;
}
Escribí esta clase de ES6 que hace el trabajo.
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;
}
}
Así es como lo usas
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 desea una versión JavaScript de vainilla, puede dirigirse al sitio web de Babel y transpilar el código allí.
Aquí hay una solución del lado del servidor basada en PhantomJS. Puede usar JSONP para realizar una llamada de dominio cruzado al servicio de imágenes:
https://github.com/vidalab/banquo-server
Por ejemplo:
Luego puede mostrar la imagen con la etiqueta img:
<img src="data:image/png;base64, [base64 data]"/>
Funciona a través del navegador.
cambiar svg
para que coincida con tu elemento
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()
Uncaught TypeError: Failed to execute 'serializeToString' on 'XMLSerializer': parameter 1 is not of type 'Node'.
Svg
a png
se puede convertir dependiendo de las condiciones:
svg
está en formato SVG (cadena) rutas :
new Path2D()
y establecer svg
como parámetrocanvas.toDataURL()
como src
.ejemplo:
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
let svgText = 'M10 10 h 80 v 80 h -80 Z';
let p = new Path2D('M10 10 h 80 v 80 h -80 Z');
ctx.stroke(p);
let url = canvas.toDataURL();
const img = new Image();
img.src = url;
Tenga en cuenta que Path2D
no es compatible ie
y es parcialmente compatible en edge. Polyfill resuelve eso:
https://github.com/nilzona/path2d-polyfill
svg
blob y dibuja sobre lienzo usando .drawImage()
:
Buena descripción: http://ramblings.mcpher.com/Home/excelquirks/gassnips/svgtopng
Tenga en cuenta que en ie obtendrá una excepción en el escenario de canvas.toDataURL (); Es porque IE tiene una restricción de seguridad demasiado alta y trata el lienzo como de solo lectura después de dibujar la imagen allí. Todos los demás navegadores restringen solo si la imagen es de origen cruzado.
canvg
biblioteca de JavaScript. Es una biblioteca separada pero tiene funciones útiles.Me gusta:
ctx.drawSvg(rawSvg);
var dataURL = canvas.toDataURL();
Recientemente descubrí un par de bibliotecas de rastreo de imágenes para JavaScript que pueden generar una aproximación aceptable al mapa de bits, tanto en tamaño como en calidad. Estoy desarrollando esta biblioteca de JavaScript y CLI:
https://www.npmjs.com/package/svg-png-converter
Que proporciona una API unificada para todos ellos, compatible con el navegador y el nodo, sin depender del DOM, y una herramienta de línea de comando.
Para convertir logotipos / dibujos animados / imágenes similares, hace un excelente trabajo. Para fotos / realismo, se necesitan algunos ajustes, ya que el tamaño de salida puede crecer mucho.
Tiene un parque infantil, aunque en este momento estoy trabajando en uno mejor, más fácil de usar, ya que se han agregado más funciones:
https://cancerberosgx.github.io/demos/svg-png-converter/playground/#