[英]Save inline SVG as JPEG/PNG/SVG
我的 html 中有一个内联 SVG,我需要能够将其保存为 JPEG、PNG 或 SVG。
我尝试了几种不同的方法,将 SVG 转换为 canvas,然后再转换为 JPEG,但我无法使这些方法正常工作。
这是我的内联 SVG 的示例。
.font { color: #ffffff; font-family: Roboto; font-weight: bold; text-transform: uppercase; }.name { font-size: 64pt; }.top-bar-text { font-size: 32pt; }.font tspan { dominant-baseline: middle; }
<link href='http://fonts.googleapis.com/css?family=Roboto:700' rel='stylesheet' type='text/css'> <svg width="256" height="256" id="icon"> <rect class="bg1" id="bg_color_1" x="0" y="0" width="256" height="256" fill="#4cbc5a" /> <path class="bg2" id="bg_color_2" d="M 0 96 L0,256 L256,256 L256,96 s -128 96 -256 0" fill="#08a21c" /> <text id="left_corner_text" x="24" y="36" width="48" height="64" class="top_bar lct font top-bar-text" text-anchor="middle" fill="#ffffff"><tspan>1</tspan></text> <text id="right_corner_text" x="232" y="36" width="48" height="64" class="top_bar rct font top-bar-text" text-anchor="middle" fill="#ffffff"><tspan>2</tspan></text> <text id="line_1_text" transform="scale(1,2)" x="128" y="90" width="256" height="192" class="l1t font name" text-anchor="middle" fill="#ffffff"><tspan>ABC</tspan></text> </svg>
此外,并非所有元素都需要导出,因为用户拥有的一些选项是删除顶角数字。
我希望当它被转换为直接下载到浏览器时。
现在这很简单。
基本思想是:
它实际上在 stackoverflow 片段之外工作
var btn = document.querySelector('button'); var svg = document.querySelector('svg'); var canvas = document.querySelector('canvas'); function triggerDownload (imgURI) { var evt = new MouseEvent('click', { view: window, bubbles: false, cancelable: true }); var a = document.createElement('a'); a.setAttribute('download', 'MY_COOL_IMAGE.png'); a.setAttribute('href', imgURI); a.setAttribute('target', '_blank'); a.dispatchEvent(evt); } btn.addEventListener('click', function () { var canvas = document.getElementById('canvas'); var ctx = canvas.getContext('2d'); var data = (new XMLSerializer()).serializeToString(svg); 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); var imgURI = canvas .toDataURL('image/png') .replace('image/png', 'image/octet-stream'); triggerDownload(imgURI); }; img.src = url; });
<button>svg to png</button> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="200" height="200"> <rect x="10" y="10" width="50" height="50" /> <text x="0" y="100">Look, i'm cool</text> </svg> <canvas id="canvas"></canvas>
关于下载部分,您可以设置文件名等(尽管在此示例中没有)。 几天前,我回答了一个关于如何从给定页面下载特定 HTML 部分的问题。 关于下载部分可能有用: https : //stackoverflow.com/a/28087280/2178180
更新:现在让您指定文件名
这是一个也适用于 IE11 的解决方案。
我只是对各种方法进行了大量测试,虽然 Ciro Costa 的上述答案非常棒,因为它适用于 Firefox 和 Chrome,但它不适用于 IE11。 由于将svg 呈现到需要画布实现canvg的画布的安全问题,IE11 失败。 这是一个使用canvg
的解决方案,它非常简洁,适用于最新版本的 Chrome、Firefox、Edge 和 IE11。
小提琴: https : //jsfiddle.net/StefanValentin/9mudw0ts/
DOM
<svg
id="my-svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1"
width="200"
height="200"
>
<rect x="10" y="10" width="50" height="50" />
<text x="0" y="100">Look, i'm cool</text>
</svg>
JavaScript
var svg = document.querySelector('#my-svg');
var data = (new XMLSerializer()).serializeToString(svg);
// We can just create a canvas element inline so you don't even need one on the DOM. Cool!
var canvas = document.createElement('canvas');
canvg(canvas, data, {
renderCallback: function() {
canvas.toBlob(function(blob) {
download('MyImageName.png', blob);
});
}
});
上面的download
函数可以是你想要做的任何事情,因为有很多方法可以通过 JavaScript 触发下载。 这是我们使用的,适用于我测试过的所有浏览器。
// Initiate download of blob
function download(
filename, // string
blob // Blob
) {
if (window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveBlob(blob, filename);
} else {
const elem = window.document.createElement('a');
elem.href = window.URL.createObjectURL(blob);
elem.download = filename;
document.body.appendChild(elem);
elem.click();
document.body.removeChild(elem);
}
}
关闭@CiroCosta。 1 个选项如果您在导出元素时遇到问题,您可以在绘制 svg 图像之前将图像绘制到画布上
btn.addEventListener('click', function () {
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var data = (new XMLSerializer()).serializeToString(svg);
var DOMURL = window.URL || window.webkitURL || window;
// get the raw image from the DOM
var rawImage = document.getElementById('yourimageID');
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(rawImage, 0, 0);
ctx.drawImage(img, 0, 0);
DOMURL.revokeObjectURL(url);
var imgURI = canvas
.toDataURL('image/png')
.replace('image/png', 'image/octet-stream');
triggerDownload(imgURI);
};
img.src = url;
});
为我工作,但仅适用于 png 和 jpeg。 SVG 文件仍然只显示内联元素而不是标签
编辑:创建像这样的 svg 的方式实际上是将图像标记转换为 Base64 并将其设置为图像属性中的 xlink:href,如下所示:
<image id="crop" width="725" height="1764" xlink:href="data:image/png;base64,iVBORw0KGgo ... " />
然后像这样在整个 svg url 上触发下载:
btn.addEventListener('click', function () {
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var data = (new XMLSerializer()).serializeToString(svg);
var DOMURL = window.URL || window.webkitURL || window;
var rawImage = document.getElementById('yourimageID');
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);
triggerDownload(url);
DOMURL.revokeObjectURL(url);
}
};
你可以像这样在这里转换png:
function getDataUri(url, callback) {
var image = new Image();
image.onload = function () {
var canvas = document.createElement('canvas');
canvas.width = this.naturalWidth; // or 'width' if you want a special/scaled size
canvas.height = this.naturalHeight; // or 'height' if you want a special/scaled size
canvas.getContext('2d').drawImage(this, 0, 0);
// Get raw image data
callback(canvas.toDataURL('image/png').replace(/^data:image\/(png|jpg);base64,/, ''));
// ... or get as Data URI
callback(canvas.toDataURL('image/png'));
};
image.src = url;
}
然后设置属性
getDataUri('localImagepath', function (dataUri) {
image.setAttribute('xlink:href', dataUri);
});
一般来说,此处提供的解决方案有效,但不要忘记以像素为单位明确设置 canvas 大小,否则图像可能会被裁剪。 例如:
// get the size of the svg image const { width, height } = svg.getBBox(); // create a canvas and set its size var canvas = document.createElement(`canvas`); canvas.setAttribute(`width`, width); canvas.setAttribute(`height`, height);
内联SVG另存为SVG文件的解决方案
适用于现代浏览器
<svg width="100" height="100">
<rect fill="red" x="0" y="0" width="100" height="100" />
</svg>
<button>Save to SVG</button>
let btn = document.querySelector('button')
let svg = document.querySelector('svg')
let triggerDownload = (imgURI, fileName) => {
let a = document.createElement('a')
a.setAttribute('download', 'image.svg')
a.setAttribute('href', imgURI)
a.setAttribute('target', '_blank')
a.click()
}
let save = () => {
let data = (new XMLSerializer()).serializeToString(svg)
let svgBlob = new Blob([data], {type: 'image/svg+xml;charset=utf-8'})
let url = URL.createObjectURL(svgBlob)
triggerDownload(url)
}
let btn = document.querySelector('button')
btn.addEventListener('click', save)
代码笔: https ://codepen.io/udovichenko/pen/yLXaWLB
@ciro costa 的答案确实有帮助,但除非设置了画布高度和宽度,否则生成的 png 高度无法正常工作。
function downloadImg() { const svgElem = document.querySelector('svg') const serializer = new XMLSerializer(); let svgData = serializer.serializeToString(svgElem); svgData = '<?xml version="1.0" standalone="no"?>\\r\\n' + svgData; const svgBlob = new Blob([svgData], { type: 'image/svg+xml;charset=utf-8', }); let DOMURL = window.URL || window.webkitURL || window; const url = DOMURL.createObjectURL(svgBlob); const img = new Image(); img.onload = () => { const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); const domRect = svgElem.getBBox(); canvas.width = domRect.width; canvas.height = domRect.height; ctx.drawImage(img, 0, 0, domRect.width, domRect.height); DOMURL.revokeObjectURL(url); const imgURI = canvas .toDataURL('image/png') .replace('image/png', 'image/octet-stream'); download(imgURI); }; img.onerror = (e) => { console.error('Image not loaded', e); }; img.src = url; } function download(href) { let download = document.createElement('a'); download.href = href; download.download = 'img.png'; download.click(); download.remove(); }
<svg width="256" height="256" id="icon"> <rect class="bg1" id="bg_color_1" x="0" y="0" width="256" height="256" fill="#4cbc5a" /> </svg> <div> <button onclick="downloadImg()">Download</button> </div>
使用此示例,但 JavaScript 部分对您来说是简化的。
function SVGPNG(svg, cb) { let temp = document.createElement("img"); let imageSrc = URL.createObjectURL( new Blob([svg], { type: "image/svg+xml" }) ); temp.src = imageSrc; temp.setAttribute("style", "position:fixed;left:-200vw;"); document.body.appendChild(temp); temp.onload = function onload() { let canvas = document.createElement("canvas"); canvas.width = temp.clientWidth; canvas.height = temp.clientHeight; let ctx = canvas.getContext("2d"); ctx.drawImage(temp, 0, 0); let src = canvas.toDataURL("image/png"); cb(src, canvas); temp.remove(); URL.revokeObjectURL(imageSrc); }; } function onPaste(e) { SVGPNG(e.target.value, (src) => { document.getElementById("output").value = src; }); }
body { font-family: system-ui; background: #f06d06; color: white; text-align: center; } textarea { border: solid 1px #ccc; border-radius: 10px; resize: none; outlined: solid 1px #999; }
<textarea cols="60" rows="20" autofocus onchange="onPaste">Paste your SVG code here...</textarea> <textarea cols="60" rows="20" readonly id="output">Your output here...</textarea>
保持简单,在 HTML 中放置一个 svg、一个画布和一个空的 img。 将所有设置为相同的大小。 javascript 将使用 svg 创建一个二进制大对象,然后将其作为 png 图像呈现在画布中。 函数调用创建画布的克隆并将其转换为 jpeg。
function fjpg(){ clone = c.cloneNode(true); ctx = clone.getContext('2d'); ctx.fillStyle = "#FFF"; ctx.fillRect(0, 0, clone.width, clone.height); ctx.drawImage(c, 0, 0); document.all.jp1.src=clone.toDataURL("image/jpeg"); ctx = c.getContext('2d'); svgBlob = new Blob( [dataPNG], { type: 'image/svg+xml' } ); urlPNG = self.URL.createObjectURL( svgBlob ); img = new Image(); img.onload = function () {ctx.drawImage(img,0,0)} img.src = urlPNG; } c = document.all.canvas0; ctx = c.getContext('2d'); data = (new XMLSerializer()).serializeToString(document.all.svg0); dataJPG = data.replace('>SVG<','>JPG<'); dataPNG = data.replace('>SVG<','>PNG<'); svgBlob = new Blob( [dataJPG], { type: 'image/svg+xml' } ); urlJPG = self.URL.createObjectURL( svgBlob ); img = new Image(); img.onload = function () { ctx.drawImage( img, 0, 0 ); fjpg(); } img.src = urlJPG;
<svg id='svg0' height=180 width=180><rect width=100% height=100% fill=red /><circle cx=90 cy=90 r=80 fill=green /><text x=90 y=105 font-size=60 text-anchor=middle fill=yellow>SVG</text></svg> <canvas id="canvas0" height=180 width=180></canvas> <img src='' id='jp1'>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.