Javascript 将内联 SVG 保存为 JPEG/PNG/SVG

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28226677/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 01:24:07  来源:igfitidea点击:

Save inline SVG as JPEG/PNG/SVG

javascriptsvgpngjpeg

提问by Tim Rideyourbike

I have an inline SVG in my html, and I need to be able to save this as either a JPEG, PNG or SVG.

我的 html 中有一个内联 SVG,我需要能够将其保存为 JPEG、PNG 或 SVG。

I have tried a few different methods with converting the SVG to canvas and then converting to JPEG, but I haven't been able to get these working.

我尝试了几种不同的方法,将 SVG 转换为画布,然后转换为 JPEG,但我一直无法使这些工作。

Here is an example of my inline SVG.

这是我的内联 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>

Also, not all the elements need to be exported, as some of the options the user has is to remove the top corner numbers.

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

I would like for when it's been converted to download straight to the browser.

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

回答by Ciro Costa

Nowadays this is pretty simple.

现在这很简单。

The basic idea is:

基本思想是:

  1. svg to canvas
  2. canvas to dataUrl
  3. trigger download from dataUrl
  1. svg 到画布
  2. 画布到 dataUrl
  3. 从 dataUrl 触发下载


it actually works outside of stackoverflow snippet

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

Regarding the downloading part, you can set up a filename and etc etc (although not in this example). Some days ago i answered a question on how to download a specific portion of HTML from the given page. It might be useful regarding the downloading part: https://stackoverflow.com/a/28087280/2178180

关于下载部分,您可以设置文件名等(尽管在此示例中没有)。几天前,我回答了一个关于如何从给定页面下载特​​定 HTML 部分的问题。关于下载部分可能有用:https: //stackoverflow.com/a/28087280/2178180

update: now letting you specify the filename

更新:现在让您指定文件名

回答by KhalilRavanna

Here's a solution that works in IE11 as well.

这是一个也适用于 IE11 的解决方案。

I just did a bunch of testing of various methods of this and while the above answer by Ciro Costa is fantastic in that it works in Firefox and Chrome it does not work in IE11. IE11 fails due to a security issuewith rendering an svg to the canvas which requires a canvas implementation, canvg. Here's a solution using canvgthat's pretty terse and works in the latest versions of Chrome, Firefox, Edge, and IE11.

我只是对各种方法进行了大量测试,虽然 Ciro Costa 的上述答案非常棒,因为它适用于 Firefox 和 Chrome,但它不适用于 IE11。由于将svg 呈现到需要画布实现canvg的画布的安全问题,IE11失败。这是一个canvg非常简洁的解决方案,适用于最新版本的 Chrome、Firefox、Edge 和 IE11。

Fiddle:https://jsfiddle.net/StefanValentin/9mudw0ts/

小提琴:https : //jsfiddle.net/StefanValentin/9mudw0ts/

DOM

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

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);
    });
  }
});

The downloadfunction above could be whatever you want to do, as there are many ways to trigger a download via JavaScript. Here's the one we use that works in all the browsers I've tested.

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);
  }
}

回答by Chadd Frasier

Working off @CiroCosta. 1 option if you are having trouble exporting an element you could just draw the image to the canvas before drawing the svg image

关闭@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;
});

Worked for me but only for png and jpeg. SVG files still only display inline elements and not tags

为我工作,但仅适用于 png 和 jpeg。SVG 文件仍然只显示内联元素而不是标签

EDIT: The way you create an svg like this is actually by converting the image tag into Base64 and the setting that as the xlink:href in the image attributes like this:

编辑:创建像这样的 svg 的方式实际上是将图像标记转换为 Base64 并将其设置为图像属性中的 xlink:href,如下所示:

<image id="crop" width="725" height="1764" xlink:href="data:image/png;base64,iVBORw0KGgo ... " />

and then triggering the download on the whole svg url like this:

然后像这样在整个 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);
  }
};

you can convert pngs like this here:

你可以像这样在这里转换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;
}

then setting the attribute

然后设置属性

getDataUri('localImagepath', function (dataUri) {
  image.setAttribute('xlink:href', dataUri);
});