Javascript 在浏览器中将SVG转换为图像(JPEG、PNG等)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3975499/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Convert SVG to image (JPEG, PNG, etc.) in the browser
提问by Zain
I want to convert SVG into bitmap images (like JPEG, PNG, etc.) through JavaScript.
我想通过 JavaScript 将 SVG 转换为位图图像(如 JPEG、PNG 等)。
采纳答案by jbeard4
Here is how you can do it through JavaScript:
您可以通过以下方式通过 JavaScript 执行此操作:
- Use the canvg JavaScript library to render the SVG image using Canvas: https://github.com/gabelerner/canvg
- Capture a data URI encoded as a JPG (or PNG) from the Canvas, according to these instructions: Capture HTML Canvas as gif/jpg/png/pdf?
- 使用canvg JavaScript 库通过Canvas 渲染SVG 图像:https: //github.com/gabelerner/canvg
- 根据以下说明从画布中捕获编码为 JPG(或 PNG)的数据 URI:将HTML 画布捕获为 gif/jpg/png/pdf?
回答by coop
jbeard4 solution worked beautifully.
jbeard4 解决方案效果很好。
I'm using Raphael SketchPadto create an SVG. Link to the files in step 1.
我正在使用Raphael SketchPad创建一个 SVG。链接到步骤 1 中的文件。
For a Save button (id of svg is "editor", id of canvas is "canvas"):
对于保存按钮(svg 的 id 是“editor”,canvas 的 id 是“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...
});
回答by worstenbrood
This seems to work in most browsers:
这似乎适用于大多数浏览器:
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;
}
回答by Thom Kiesewetter
The solution to convert SVG to blob URL and blob URL to png image
SVG转blob URL和blob URL转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;
}
回答by Phuoc Do
Here's a server side solution based on PhantomJS. You can use JSONP to make a cross domain call to the image service:
这是一个基于 PhantomJS 的服务器端解决方案。您可以使用 JSONP 对影像服务进行跨域调用:
https://github.com/vidalab/banquo-server
https://github.com/vidalab/banquo-server
For example:
例如:
Then you can display image with img tag:
然后你可以用 img 标签显示图像:
<img src="data:image/png;base64, [base64 data]"/>
It works across browser.
它跨浏览器工作。
回答by Cels
I wrote this ES6 Class which does the Job.
我写了这个 ES6 类来完成这项工作。
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;
}
}
Here is how you use it
这是你如何使用它
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.
});
If you want a vanilla JavaScript version, you could head over to Babel websiteand transpile the code there.
如果你想要一个普通的 JavaScript 版本,你可以前往 Babel 网站并在那里转译代码。
回答by Alex Vovchuk
Svgto pngcan be converted depending on conditions:
Svg到png可根据条件被转换:
- If
svgis in format SVG (string) paths:- create canvas
- create
new Path2D()and setsvgas parameter - draw path on canvas
- create image and use
canvas.toDataURL()assrc.
- 如果
svg是格式SVG(字符串)路径:- 创建画布
- 创建
new Path2D()并设置svg为参数 - 在画布上绘制路径
- 创建图像并
canvas.toDataURL()用作src.
example:
例子:
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;
Note that Path2Dnot supported in ieand partially supported in edge. Polyfill solves that:
https://github.com/nilzona/path2d-polyfill
请注意,边缘Path2D不支持ie和部分支持。Polyfill 解决了这个问题:https:
//github.com/nilzona/path2d-polyfill
- Create
svgblob and draw on canvas using.drawImage():- make canvas element
- make a svgBlob object from the svg xml
- make a url object from domUrl.createObjectURL(svgBlob);
- create an Image object and assign url to image src
- draw image into canvas
- get png data string from canvas: canvas.toDataURL();
- 创建
svgblob 并使用.drawImage()以下命令在画布上绘制:- 制作画布元素
- 从 svg xml 创建一个 svgBlob 对象
- 从 domUrl.createObjectURL(svgBlob) 创建一个 url 对象;
- 创建一个 Image 对象并将 url 分配给 image src
- 将图像绘制到画布中
- 从画布中获取 png 数据字符串:canvas.toDataURL();
Nice description: http://ramblings.mcpher.com/Home/excelquirks/gassnips/svgtopng
很好的描述:http: //ramblings.mcpher.com/Home/excelquirks/gassnips/svgtopng
Note that in ie you will get exception on stage of canvas.toDataURL(); It is because IE has too high security restriction and treats canvas as readonly after drawing image there. All other browsers restrict only if image is cross origin.
请注意,在 ie 中,您将在 canvas.toDataURL(); 的阶段获得异常;这是因为 IE 的安全限制太高,在那里绘制图像后将画布视为只读。所有其他浏览器仅在图像跨原点时进行限制。
- Use
canvgJavaScript library. It is separate library but has useful functions.
- 使用
canvgJavaScript 库。它是单独的库,但具有有用的功能。
Like:
喜欢:
ctx.drawSvg(rawSvg);
var dataURL = canvas.toDataURL();
回答by Mahdi Khalili
change svgto match your element
更改svg以匹配您的元素
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()
回答by cancerbero
I recently discovered a couple of image tracing libraries for JavaScript that indeed are able to build an acceptable approximation to the bitmap, both size and quality. I'm developing this JavaScript library and CLI :
我最近发现了几个用于 JavaScript 的图像跟踪库,它们确实能够构建可接受的位图近似值,包括大小和质量。我正在开发这个 JavaScript 库和 CLI:
https://www.npmjs.com/package/svg-png-converter
https://www.npmjs.com/package/svg-png-converter
Which provides unified API for all of them, supporting browser and node, non depending on DOM, and a Command line tool.
为所有这些提供统一的API,支持浏览器和节点,不依赖于DOM,以及一个命令行工具。
For converting logos/cartoon/like images it does excellent job. For photos / realism some tweaking is needed since the output size can grow a lot.
对于转换徽标/卡通/类似图像,它做得很好。对于照片/现实主义,需要进行一些调整,因为输出大小可能会增加很多。
It has a playground although right now I'm working on a better one, easier to use, since more features has been added:
它有一个操场,尽管现在我正在开发一个更好的,更易于使用的操场,因为添加了更多功能:
https://cancerberosgx.github.io/demos/svg-png-converter/playground/#
https://cancerberosgx.github.io/demos/svg-png-converter/playground/#

