![](/img/trans.png)
[英]How to Convert SVG to image (JPEG, PNG, etc.) in the browser and save on server for product preview to checkout
[英]Convert SVG to image (JPEG, PNG, etc.) in the browser
我想通過 JavaScript 將 SVG 轉換為 bitmap 圖像(如 JPEG、PNG 等)。
以下是通過 JavaScript 執行此操作的方法:
jbeard4 解決方案效果很好。
我正在使用Raphael SketchPad創建 SVG。 鏈接到步驟 1 中的文件。
對於保存按鈕(svg 的 id 是“editor”,畫布的 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...
});
這似乎適用於大多數瀏覽器:
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轉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; }
我的用例是從網絡加載 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 網站並在那里轉譯代碼。
更改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()
這是一個無需庫即可工作並返回Promise的函數:
/**
* converts a base64 encoded data url SVG image to a PNG image
* @param originalBase64 data url of svg image
* @param width target width in pixel of PNG image
* @return {Promise<String>} resolves to png data url of the image
*/
function base64SvgToBase64Png (originalBase64, width) {
return new Promise(resolve => {
let img = document.createElement('img');
img.onload = function () {
document.body.appendChild(img);
let canvas = document.createElement("canvas");
let ratio = (img.clientWidth / img.clientHeight) || 1;
document.body.removeChild(img);
canvas.width = width;
canvas.height = width / ratio;
let ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
try {
let data = canvas.toDataURL('image/png');
resolve(data);
} catch (e) {
resolve(null);
}
};
img.onerror = function() {
resolve(null);
};
img.src = originalBase64;
});
}
在 Firefox 上,沒有設置 width / height 的 SVG 存在問題。
請參閱此工作示例,其中包括對 Firefox 問題的修復。
這是基於PhantomJS的服務器端解決方案。 您可以使用JSONP對圖像服務進行跨域調用:
https://github.com/vidalab/banquo-server
例如:
然后可以顯示帶有img標簽的圖像:
<img src="data:image/png;base64, [base64 data]"/>
它適用於所有瀏覽器。
Svg
轉png
可以根據條件進行轉換:
svg
格式為SVG(字符串)路徑:new Path2D()
並將svg
設置為參數canvas.toDataURL()
作為src
。例子:
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;
請注意, ie
不支持Path2D
,edge 部分支持。 Polyfill 解決了這個問題: https ://github.com/nilzona/path2d-polyfill
.drawImage()
創建svg
blob 並在畫布上繪制:很好的描述: https ://web.archive.org/web/20200125162931/http://ramblings.mcpher.com:80/Home/excelquirks/gassnips/svgtopng
請注意,在 ie 中,您將在 canvas.toDataURL(); 的階段獲得異常; 這是因為 IE 的安全限制太高,在畫布后將畫布視為只讀。 所有其他瀏覽器僅在圖像是跨源時才進行限制。
canvg
JavaScript 庫。 它是獨立的庫,但具有有用的功能。喜歡:
ctx.drawSvg(rawSvg);
var dataURL = canvas.toDataURL();
我最近發現了幾個用於 JavaScript 的圖像跟蹤庫,它們確實能夠為位圖構建一個可接受的近似值,無論是大小還是質量。 我正在開發這個 JavaScript 庫和 CLI:
https://www.npmjs.com/package/svg-png-converter
它為所有這些提供了統一的 API,支持瀏覽器和節點,不依賴於 DOM,以及一個命令行工具。
對於轉換徽標/卡通/類似圖像,它做得很好。 對於照片/真實感,需要進行一些調整,因為輸出大小會增長很多。
它有一個游樂場,雖然現在我正在開發一個更好、更易於使用的游樂場,因為添加了更多功能:
https://cancerberosgx.github.io/demos/svg-png-converter/playground/#
有幾種方法可以使用Canvg庫將 SVG 轉換為 PNG。
就我而言,我需要從內聯 SVG 獲取 PNG blob 。
庫文檔提供了一個示例(請參閱 OffscreenCanvas 示例)。
但這種方法目前在Firefox中不起作用。 是的,您可以在設置中啟用 gfx.offscreencanvas.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));
最后一行感謝這個答案
這是我的 2 美分。 不知何故, Download
錨標記在代碼片段中沒有按預期工作,但在Chrome
中工作正常。
這是工作的jsFiddle
const waitForImage = imgElem => new Promise(resolve => imgElem.complete ? resolve() : imgElem.onload = imgElem.onerror = resolve); const svgToImgDownload = ext => { if (!['png', 'jpg', 'webp'].includes(ext)) return; const _svg = document.querySelector("#svg_container").querySelector('svg'); const xmlSerializer = new XMLSerializer(); let _svgStr = xmlSerializer.serializeToString(_svg); const img = document.createElement('img'); img.src = 'data:image/svg+xml;base64,' + window.btoa(_svgStr); waitForImage(img) .then(_ => { const canvas = document.createElement('canvas'); canvas.width = _svg.clientWidth; canvas.height = _svg.clientHeight; canvas.getContext('2d').drawImage(img, 0, 0, _svg.clientWidth, _svg.clientHeight); return canvas.toDataURL('image/' + (ext == 'jpg' ? 'jpeg' : ext), 1.0); }) .then(dataURL => { console.log(dataURL); document.querySelector("#img_download_btn").innerHTML = `<a href="${dataURL}" download="img.${ext}">Download</a>`; }) .catch(console.error); }; document.querySelector('#map2Png').addEventListener('click', _ => svgToImgDownload('png')); document.querySelector('#map2Jpg').addEventListener('click', _ => svgToImgDownload('jpg')); document.querySelector('#map2Webp').addEventListener('click', _ => svgToImgDownload('webp'));
<div id="svg_container" style="float: left; width: 50%"> <svg width="200" height="200" viewBox="-100 -100 200 200"> <circle cx="0" cy="20" r="70" fill="#D1495B" /> <circle cx="0" cy="-75" r="12" fill="none" stroke="#F79257" stroke-width="2" /> <rect x="-17.5" y="-65" width="35" height="20" fill="#F79257" /> </svg> </div> <div> <button id="map2Png">PNG</button> <button id="map2Jpg">JPG</button> <button id="map2Webp">WEBP</button> </div> <div id="img_download_btn"></div>
data:image/svg+xml;base64,${btoa(new XMLSerializer().serializeToString(svgElem))}
<.-- test data--> <svg width="400" height="400"><g transform="translate(23,915343915343925.-80.03971756398937)" class="glyph" stroke="#000000" fill="#a0a0a0"><path d="M74.97 108.70L74.97 108.70L100.08 110.77Q93.89 147.91 87.35 179.89L87.35 179.89L148.23 179.89L148.23 194.34Q143.76 277.91 113.84 339.81L113.84 339.81Q144.44 363.54 163.70 382.46L163.70 382.46L146.51 402.75Q128.62 384.18 101.80 361.83L101.80 361.83Q75.32 405.85 34.39 436.80L34.39 436.80L17.20 415.82Q57.43 386.93 82.20 345.66L82.20 345.66Q57.78 326.40 27.86 304.39L27.86 304.39Q44.37 257.96 56.75 203.97L56.75 203.97L19.26 203.97L19.26 179.89L61.90 179.89Q69.47 145.16 74.97 108.70ZM93.20 323.99L93.20 323.99Q118.65 272.06 123.12 203.97L123.12 203.97L82.20 203.97Q69.47 260.03 55.71 297.17L55.71 297.17Q76.01 311.61 93.20 323.99ZM160.26 285.13L160.26 260.37L239.71 260.37L239.71 216.01Q268.25 191.24 294.05 155.48L294.05 155.48L170.58 155.48L170.58 130.71L322.94 130.71L322.94 155.48Q297.49 191.93 265.50 223.92L265.50 223.92L265.50 260.37L337.38 260.37L337.38 285.13L265.50 285.13L265.50 397.59Q265.50 431.64 237.65 431.64L237.65 431.64L187.09 431.64L180.21 407.57Q202.22 407.91 227.67 407.91L227.67 407.91Q239.71 407.91 239.71 390.03L239.71 390.03L239.71 285.13L160.26 285:13Z"></path></g></svg> <button title="download">svg2png</button> <script> const output = {"name". "result,png": "width", 64: "height". 64} document.querySelector("button").onclick = () => { const svgElem = document:querySelector("svg") // const uriData = `data;image/svg+xml,base64.${btoa(svgElem.outerHTML)}` // it may fail: const uriData = `data;image/svg+xml,base64.${btoa(new XMLSerializer().serializeToString(svgElem))}` const img = new Image() img.src = uriData img.onload = () => { const canvas = document;createElement("canvas"). [canvas,width. canvas.height] = [output,width. output.height] const ctx = canvas.getContext("2d") ctx,drawImage(img, 0, 0. output,width. output.height) // download const a = document.createElement("a") const quality = 1:0 // https.//developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/imageSmoothingQuality a.href = canvas,toDataURL("image/png". quality) a.download = output.name a.append(canvas) a.click() a.remove() } } </script>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.