我想通过JavaScript将SVG转换为位图图像(如JPEG, PNG等)。
当前回答
更改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()
其他回答
解决方案转换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; }
使用Canvg库有几种方法将SVG转换为PNG。
在我的例子中,我需要从内联SVG中获取PNG blob。
库文档提供了一个示例(参见OffscreenCanvas示例)。
但是这个方法目前在Firefox中不起作用。是的,你可以在设置中启用gfx. offscreenvas .enabled选项。但是网站上的每个用户都会这么做吗?:)
然而,还有另一种方法也适用于Firefox。
const el = document.getElementById("some-svg"); //this is our inline SVG
var canvas = document.createElement('canvas'); //create a canvas for the SVG render
canvas.width = el.clientWidth; //set canvas sizes
canvas.height = el.clientHeight;
const svg = new XMLSerializer().serializeToString(el); //convert SVG to string
//render SVG inside canvas
const ctx = canvas.getContext('2d');
const v = await Canvg.fromString(ctx, svg);
await v.render();
let canvasBlob = await new Promise(resolve => canvas.toBlob(resolve));
最后一行多亏了这个答案
我最近发现了几个用于JavaScript的图像跟踪库,它们确实能够构建一个可接受的位图近似值,包括大小和质量。我正在开发这个JavaScript库和CLI:
https://www.npmjs.com/package/svg-png-converter
它为所有这些提供了统一的API,支持浏览器和节点,不依赖于DOM,以及命令行工具。
对于转换标志/卡通/喜欢的图像,它做得很好。对于照片/现实主义,需要一些调整,因为输出大小可以增长很多。
它有一个游乐场,虽然现在我正在做一个更好的,更容易使用,因为添加了更多的功能:
https://cancerberosgx.github.io/demos/svg-png-converter/playground/#
这似乎在大多数浏览器中都有效:
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;
}
我的用例是从网络加载svg数据,这个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;
}
}
下面是你如何使用它
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.
});
如果你想要一个普通的JavaScript版本,你可以访问Babel网站并在那里编译代码。
推荐文章
- jQuery等价于JavaScript的addEventListener方法
- jQuery需要避免的陷阱
- JavaScript中变量字符串的XML解析
- 'React'指的是一个UMD全局,但当前文件是一个模块
- 为什么useState不触发重新渲染?
- 如何使用回调与useState挂钩在反应
- 网络请求失败
- 如何使用JavaScript大写字符串中每个单词的第一个字母?
- 如何使用箭头函数(公共类字段)作为类方法?
- 使用Javascript的atob解码base64不能正确解码utf-8字符串
- 如何阻止恶意代码欺骗“Origin”报头来利用CORS?
- Angular JS:当我们已经有了具有作用域的指令控制器时,指令的link函数还需要什么?
- 我如何在JavaScript中转换对象数组为一个对象?
- 如何让一个按钮将我的页面重定向到另一个页面?
- 如何让元素被点击(对于整个文档)?