在浏览器中将SVG转换为图像(JPEG、PNG等)

IT技术 javascript svg
2021-01-11 08:39:06

我想通过 JavaScript 将 SVG 转换为位图图像(如 JPEG、PNG 等)。

6个回答

以下是您可以通过 JavaScript 执行此操作的方法:

  1. 使用canvg JavaScript 库通过Canvas 渲染SVG 图像:https : //github.com/gabelerner/canvg
  2. 根据以下说明从画布中捕获编码为 JPG(或 PNG)的数据 URI:将HTML 画布捕获为 gif/jpg/png/pdf?
如果浏览器支持 SVG 和画布,那么将有一种更简单的方法将 SVG 加载到内存中,然后将其绘制到画布中,而不需要 Canvg,这是一个非常大的库,因为它处理所有 SVG 解析支持 SVG 的浏览器已经免费提供。我不确定这是否满足原始用例,但如果满足,请参阅此资源以了解详细信息
2021-03-22 08:39:06
您现在可以使用 JavaScript SVG 库Pablo来实现这一点(我做到了)。有关自动下载的图像,请参阅toImage()download()
2021-03-22 08:39:06
感谢您不支持 IE8。人们应该明白是时候继续前进了。
2021-03-31 08:39:06
这不是严格的 Javascript,而是 HTML5。这不适用于 IE8 或任何其他不支持 HTML5 Canvas 的浏览器。
2021-04-01 08:39:06
svgopen.org/2010/papers/62-From_SVG_to_Canvas_and_Back - 完美运行![在链接页面, sourceSVG = $("#your_svg_elem_name").get(0) ]
2021-04-07 08:39:06

jbeard4 解决方案效果很好。

我正在使用Raphael SketchPad创建一个 SVG。链接到步骤 1 中的文件。

对于保存按钮(svg 的 id 是“editor”,canvas 的 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...
});
@Luckyn 和 @jonathanGB,你不应该html()在包装器上使用,或者手动构建父svg标签——它甚至可能有你在这个 hack 中遗漏的属性。只需使用即可$(svg_elem)[0].outerHTML为您提供 svg 及其内容的完整来源。就是说...
2021-03-28 08:39:06
@Lucky 如果您调用svg元素$(selector).html()的父元素,它将起作用
2021-03-29 08:39:06
canvg 需要第二个参数,<svg>...</svg但 jquery html() 函数不添加 svg 标签,所以这段代码对我有用,但我需要实时编辑 canvgcanvg('canvas', '<svg>'+$("#editor").html()+'</svg>');
2021-04-08 08:39:06

这似乎适用于大多数浏览器:

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;
}
这在 IE11 中不起作用,因为存在安全问题 .msToBlob()
2021-03-11 08:39:06
你能提供一个使用示例吗?
2021-03-25 08:39:06
谢谢!!我喜欢这对“本地”SVG HTML 节点和远程 SVG URL 的工作方式。此外,它不需要完整的外部库
2021-03-29 08:39:06

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(例如带有图像的图案)
2021-03-17 08:39:06

我的用例是从网络加载 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 网站并在那里转译代码。