简体   繁体   English

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

[英]Save inline SVG as JPEG/PNG/SVG

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 转换为 canvas,然后再转换为 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.我希望当它被转换为直接下载到浏览器时。

Nowadays this is pretty simple.现在这很简单。

The basic idea is:基本思想是:

  1. svg to canvas svg 到画布
  2. canvas to dataUrl画布到 dataUrl
  3. trigger download from dataUrl从 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.几天前,我回答了一个关于如何从给定页面下载特​​定 HTML 部分的问题。 It might be useful regarding the downloading part: https://stackoverflow.com/a/28087280/2178180关于下载部分可能有用: https : //stackoverflow.com/a/28087280/2178180

update : now letting you specify the filename更新:现在让您指定文件名

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.我只是对各种方法进行了大量测试,虽然 Ciro Costa 的上述答案非常棒,因为它适用于 Firefox 和 Chrome,但它不适用于 IE11。 IE11 fails due to a security issue with rendering an svg to the canvas which requires a canvas implementation, canvg . 由于将svg 呈现到需要画布实现canvg的画布的安全问题,IE11 失败 Here's a solution using canvg that's pretty terse and works in the latest versions of Chrome, Firefox, Edge, and 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 download function above could be whatever you want to do, as there are many ways to trigger a download via JavaScript.上面的download函数可以是你想要做的任何事情,因为有很多方法可以通过 JavaScript 触发下载。 Here's the one we use that works in all the browsers I've tested.这是我们使用的,适用于我测试过的所有浏览器。

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

Working off @CiroCosta.关闭@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 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.为我工作,但仅适用于 png 和 jpeg。 SVG files still only display inline elements and not tags 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);
});

In general, the solutions presented here work, but don't forget to explicitly set the canvas size in pixels, otherwise the image may be cropped.一般来说,此处提供的解决方案有效,但不要忘记以像素为单位明确设置 canvas 大小,否则图像可能会被裁剪。 For example:例如:

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

The solution for saving inline SVG as SVG file内联SVG另存为SVG文件的解决方案

Works in modern browsers适用于现代浏览器

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

Codepen: https://codepen.io/udovichenko/pen/yLXaWLB代码笔: https ://codepen.io/udovichenko/pen/yLXaWLB

The answer by @ciro costa does help, but the generated png height is not working correctly unless the canvas height and width is set. @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>

Use this to example, but JavaScript section is simplify to you.使用此示例,但 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>

Keeping it simple, place an svg, a canvas and an empty img into the HTML.保持简单,在 HTML 中放置一个 svg、一个画布和一个空的 img。 Set all to the same size.将所有设置为相同的大小。 The javascript will use the svg to create a binary large object which is then rendered in the canvas as a png image. javascript 将使用 svg 创建一个二进制大对象,然后将其作为 png 图像呈现在画布中。 The function call creates a clone of the canvas and converts it into a jpeg.函数调用创建画布的克隆并将其转换为 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