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

时间:2015-01-29 23:31:01

标签: javascript svg png jpeg

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

我尝试了一些不同的方法,将SVG转换为画布然后转换为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>

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

我想将它转换为直接下载到浏览器。

4 个答案:

答案 0 :(得分:51)

现在这很简单。

基本理念是:

  1. svg to canvas
  2. canvas to dataUrl
  3. 从dataUrl触发下载

  4. 它实际上在stackoverflow代码段之外工作

    &#13;
    &#13;
    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;
    });
    &#13;
    <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>
    &#13;
    &#13;
    &#13;

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

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

答案 1 :(得分:1)

正在处理@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网址的下载:

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

您可以像这样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;
        }

然后设置属性

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

答案 2 :(得分:0)

这也是在IE11中也可以使用的解决方案。

我只是对各种方法进行了一系列测试,尽管Ciro Costa的上述回答非常棒,因为它可以在Firefox和Chrome中运行,而在IE11中却不起作用。 IE11 fails due to a security issue,可将svg渲染到画布,这需要画布实现canvg。这是一个使用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);
  }
}

答案 3 :(得分:-1)

保持简单,将svg,画布和空img放入HTML。将所有设置为相同的大小。 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'>