繁体   English   中英

将内联 SVG 另存为 JPEG/PNG/SVG

[英]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>

此外,并非所有元素都需要导出,因为用户拥有的一些选项是删除顶角数字。

我希望当它被转换为直接下载到浏览器时。

现在这很简单。

基本思想是:

  1. svg 到画布
  2. 画布到 dataUrl
  3. 从 dataUrl 触发下载

它实际上在 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM