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
Svg
to png
can be converted depending on conditions:
Svg
到png
可根据条件被转换:
- If
svg
is in format SVG (string) paths:- create canvas
- create
new Path2D()
and setsvg
as 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 Path2D
not supported in ie
and partially supported in edge. Polyfill solves that:
https://github.com/nilzona/path2d-polyfill
请注意,边缘Path2D
不支持ie
和部分支持。Polyfill 解决了这个问题:https:
//github.com/nilzona/path2d-polyfill
- Create
svg
blob 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();
- 创建
svg
blob 并使用.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
canvg
JavaScript library. It is separate library but has useful functions.
- 使用
canvg
JavaScript 库。它是单独的库,但具有有用的功能。
Like:
喜欢:
ctx.drawSvg(rawSvg);
var dataURL = canvas.toDataURL();
回答by Mahdi Khalili
change svg
to 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/#