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

Convert SVG to image (JPEG, PNG, etc.) in the browser

提问人:Zain 提问时间:10/20/2010 最后编辑:PhrogzZain 更新时间:10/24/2023 访问量:469931

问:

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

JavaScript SVG

评论

0赞 aaaaaaaaaaaa 10/20/2010
你真正想完成的任务是什么?尽管回声流的答案告诉我们(在某些浏览器中)有可能,但对于几乎所有实际情况,都有更好、更简单的转换方法。
2赞 ace 5/15/2014
下面是使用 d3 的示例: stackoverflow.com/a/23667012/439699
0赞 Vijay Singh 4/25/2016
svgopen.org/2010/papers/62-From_SVG_to_Canvas_and_Back - 完美工作![在链接页面上,sourceSVG = $(“#your_svg_elem_name”).get(0) ]
0赞 mathheadinclouds 5/31/2020
相关新闻: stackoverflow.com/questions/3173048/...
0赞 natenho 4/17/2021
mybyways.com/blog/convert-svg-to-png-using-your-browser

答:

282赞 jbeard4 10/20/2010 #1

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

  1. 使用 canvg JavaScript 库使用 Canvas 渲染 SVG 图像:https://github.com/gabelerner/canvg
  2. 根据以下说明从 Canvas 捕获编码为 JPG(或 PNG)的数据 URI: 将 HTML Canvas 捕获为 gif/jpg/png/pdf?

评论

31赞 James 6/26/2012
这不是严格意义上的 Javascript,而是 HTML5。这不适用于 IE8 或任何其他不支持 HTML5 Canvas 的浏览器。
192赞 Sanket Sahu 1/31/2014
感谢您不支持 IE8。人们应该明白,是时候继续前进了。
11赞 Prem 9/15/2014
您现在可以使用 JavaScript SVG 库 Pablo 来实现这一点(我做到了)。请参阅 toImage() 和 download() 以获取自动下载的图像。
2赞 daniel 11/22/2017
canvg 不完整。例如,它不支持掩码。
1赞 Andru 5/4/2018
@Premasagar不幸的是,该链接不起作用,但您的评论听起来很有趣。
48赞 coop 6/27/2012 #2

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

评论

1赞 Luckyn 5/20/2015
canvg 需要第二个参数,但 jquery html() 函数不添加 svg 标签,所以这段代码对我有用,但我需要将 canvg 实时编辑到<svg>...</svgcanvg('canvas', '<svg>'+$("#editor").html()+'</svg>');
1赞 jonathanGB 8/13/2016
@Luckyn,如果您调用 svg 元素的父元素,它将起作用$(selector).html()
1赞 JWL 10/19/2016
@Luckyn和@jonathanGB,你不应该在包装器上使用,或者手动构造父标签 - 它甚至可能具有你在这个黑客中遗漏的属性。只需使用即可为您提供 svg 及其内容的完整源代码。只是说...html()svg$(svg_elem)[0].outerHTML
36赞 worstenbrood 6/27/2017 #3

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

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

评论

4赞 Florian Leitgeb 6/5/2018
这在 IE11 中不起作用,因为.msToBlob()
1赞 Rudolf Real 11/15/2019
谢谢!!我喜欢它对“本地”SVG HTML 节点和远程 SVG URL 的工作方式。此外,它不需要完整的外部库
5赞 Neil 7/29/2020
您能提供一个使用示例吗?
2赞 Augusto Peres 3/12/2022
这个 copyStylesInline 对我帮助很大!!如果不添加,我导出的 png 看起来很奇怪。谢谢!
0赞 Kle0s 1/10/2023
我在使用 SVGAnimateElement 时遇到了问题(因为动画不会影响 SVG 的样式),其他人遇到过吗?
11赞 Mahdi Khalili 11/21/2018 #4

更改以匹配您的元素svg

function svg2img(){
    var svg = document.querySelector('svg');
    var xml = new XMLSerializer().serializeToString(svg);
    var svg64 = btoa(xml); //for utf8: btoa(unescape(encodeURIComponent(xml)))
    var b64start = 'data:image/svg+xml;base64,';
    var image64 = b64start + svg64;
    return image64;
};svg2img()

评论

2赞 Xsmael 12/15/2018
它对我不起作用,我收到此错误:Uncaught TypeError: Failed to execute 'serializeToString' on 'XMLSerializer': parameter 1 is not of type 'Node'.
1赞 Mahdi Khalili 12/15/2018
@Xsmael尝试将 DOMParser 接口切换 developer.mozilla.org/en-US/docs/Web/API/DOMParser
0赞 Lex Soft 7/12/2020
谢谢,这对我有用。无需使用外部库。
1赞 Mahdi Khalili 1/7/2021
@RyanArqueza怎么做?
1赞 Mahdi Khalili 5/18/2021
@MTZ您应该考虑将 utf8 部分用于 utf8 字符,例如,您的 SVG 包含非 ASCI 字符
1赞 cancerbero 6/19/2019 #5

我最近发现了几个用于 JavaScript 的图像跟踪库,它们确实能够构建可接受的位图近似值,包括大小和质量。我正在开发这个 JavaScript 库和 CLI:

https://www.npmjs.com/package/svg-png-converter

它为所有这些提供了统一的 API,支持浏览器和节点,不依赖于 DOM,以及命令行工具。

对于转换徽标/卡通/类似图像,它做得很好。对于照片/真实感,需要进行一些调整,因为输出大小可能会增长很多。

它有一个游乐场,尽管现在我正在研究一个更好的游乐场,更易于使用,因为添加了更多功能:

https://cancerberosgx.github.io/demos/svg-png-converter/playground/#

11赞 Cels 7/23/2019 #6

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

31赞 Thom Kiesewetter 9/28/2019 #7

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

评论

0赞 Djov 11/23/2020
此解决方案不适用于复杂的 SVG(例如带有图像的图案)
1赞 Alejandro Reyes 12/21/2021
这是您的代码,但已优化,但感谢您...codepen.io/arcaelas-the-looper/pen/wvrqzvm
1赞 Haseeb Saeed 1/12/2022
谢谢你@AlejandroReyes
0赞 Alejandro Reyes 1/13/2022
不客气,可以在github上关注我:arcaelas
0赞 puaaaal 11/13/2022
出于某种原因,当我使用 时,一些 SVG 被污染了(我怀疑这与它们在其中定义了 \<style\> 有关),但后来我尝试从头开始创建数据 url,如下所示: ,它完美无缺!您也可以像这样使用 base64: .我正在使用电子URL.createObjectURL(new Blob([svg], { type: 'image/svg+xml' }))'data:image/svg+xml;utf-8,${svg.replace(/#/g, '%23').replace(/\n/g, '%0A')}';'data:image/svg+xml;base64,${btoa(drawing)}';
2赞 Alex Vovchuk 10/26/2019 #8

Svg可以根据条件进行转换:png

  1. 如果格式为 SVG(字符串)路径svg
  • 创建画布
  • 创建并设置为参数new Path2D()svg
  • 在画布上绘制路径
  • 创建映像并用作 .canvas.toDataURL()src

例:

const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
let svgText = 'M10 10 h 80 v 80 h -80 Z';
let p = new Path2D('M10 10 h 80 v 80 h -80 Z');
ctx.stroke(p);
let url = canvas.toDataURL();
const img = new Image();
img.src = url;

请注意,在 Edge 中不受支持,在 Edge 中部分受支持。Polyfill 解决了以下问题: https://github.com/nilzona/path2d-polyfillPath2Die

  1. 使用以下命令创建 blob 并在画布上绘制:svg.drawImage()
  • make canvas 元素
  • 从 svg xml 创建一个 svgBlob 对象
  • 从 domUrl.createObjectURL(svgBlob) 创建一个 url 对象;
  • 创建一个 Image 对象并将 url 分配给图像 src
  • 将图像绘制到画布中
  • 从 canvas 获取 png 数据字符串: canvas.toDataURL();

不错的描述: https://web.archive.org/web/20200125162931/http://ramblings.mcpher.com:80/Home/excelquirks/gassnips/svgtopng

请注意,在 ie,您将在 canvas.toDataURL() 阶段获得异常;这是因为IE的安全限制太高,在画布上绘制图像后将画布视为只读。所有其他浏览器仅在图像是跨源时才限制。

  1. 使用 JavaScript 库。它是独立的库,但具有有用的功能。canvg

喜欢:

ctx.drawSvg(rawSvg);
var dataURL = canvas.toDataURL();

评论

1赞 Serdar Sayın 6/11/2020
第 3 个链接已断开
1赞 Alex Vovchuk 6/11/2020
是的,确实如此。我现在不知道如何到达那里。但上面的描述足以理解一些。将来在引用后复制一些上下文的好主意
0赞 albert 9/21/2020
修复了 linkrot。Wayback Machine 是您修复 Linkrot 的朋友。
10赞 klues 11/12/2020 #9

这里有一个函数,它没有库,并返回一个 Promise

/**
 * converts a base64 encoded data url SVG image to a PNG image
 * @param originalBase64 data url of svg image
 * @param width target width in pixel of PNG image
 * @return {Promise<String>} resolves to png data url of the image
 */
function base64SvgToBase64Png (originalBase64, width) {
    return new Promise(resolve => {
        let img = document.createElement('img');
        img.onload = function () {
            document.body.appendChild(img);
            let canvas = document.createElement("canvas");
            let ratio = (img.clientWidth / img.clientHeight) || 1;
            document.body.removeChild(img);
            canvas.width = width;
            canvas.height = width / ratio;
            let ctx = canvas.getContext("2d");
            ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
            try {
                let data = canvas.toDataURL('image/png');
                resolve(data);
            } catch (e) {
                resolve(null);
            }
        };
        img.onerror = function() {
            resolve(null);
        };
        img.src = originalBase64;
    });
}

在Firefox上,没有设置宽度/高度的SVG存在问题

请参阅此工作示例,其中包括对Firefox问题的修复。

评论

0赞 chrisheseltine 2/4/2021
在Safari中对我不起作用,只是挂了,没有错误
0赞 klues 2/5/2021
感谢您的测试,我以前没有使用Safari进行过测试。所以 Javascript 控制台也没有错误,这会很奇怪吗?
0赞 chrisheseltine 2/6/2021
是的,在我的经验中很奇怪,但不幸的是,我没有更多的时间可以浪费
0赞 Nate 8/18/2021
感谢您包含这个奇妙的例子!
0赞 Fredrik Blomqvist 6/3/2022
1)我建议附加img.onerror,以免在这种情况下拖延Promise。2) 您不必将图像附加到 document.body。
1赞 foske 1/28/2021 #10

有几种方法可以使用 Canvg 库将 SVG 转换为 PNG。

就我而言,我需要从内联 SVG 获取 PNG blob

库文档提供了一个示例(请参阅 OffscreenCanvas 示例)。

但是这种方法目前在Firefox不起作用。是的,您可以在设置中启用 gfx.offscreencanvas.enabled 选项。但是网站上的每个用户都会这样做吗?:)

但是,还有另一种方法也可以在Firefox中使用。

const el = document.getElementById("some-svg"); //this is our inline SVG

var canvas = document.createElement('canvas'); //create a canvas for the SVG render
canvas.width = el.clientWidth; //set canvas sizes
canvas.height = el.clientHeight;

const svg = new XMLSerializer().serializeToString(el); //convert SVG to string

//render SVG inside canvas
const ctx = canvas.getContext('2d');
const v = await Canvg.fromString(ctx, svg);
await v.render();

let canvasBlob = await new Promise(resolve => canvas.toBlob(resolve));

最后一行感谢这个答案

0赞 Umair Khan 7/21/2022 #11

这是我的 2 美分。不知何故,锚标记在代码片段中未按预期工作,但是它在 中工作正常。DownloadChrome

这是工作 jsFiddle

const waitForImage = imgElem => new Promise(resolve => imgElem.complete ? resolve() : imgElem.onload = imgElem.onerror = resolve);

const svgToImgDownload = ext => {
  if (!['png', 'jpg', 'webp'].includes(ext))
    return;
  const _svg = document.querySelector("#svg_container").querySelector('svg');
  const xmlSerializer = new XMLSerializer();
  let _svgStr = xmlSerializer.serializeToString(_svg);
  const img = document.createElement('img');
  img.src = 'data:image/svg+xml;base64,' + window.btoa(_svgStr);
  waitForImage(img)
    .then(_ => {
      const canvas = document.createElement('canvas');
      canvas.width = _svg.clientWidth;
      canvas.height = _svg.clientHeight;
      canvas.getContext('2d').drawImage(img, 0, 0, _svg.clientWidth, _svg.clientHeight);
      return canvas.toDataURL('image/' + (ext == 'jpg' ? 'jpeg' : ext), 1.0);
    })
    .then(dataURL => {
      console.log(dataURL);
      document.querySelector("#img_download_btn").innerHTML = `<a href="${dataURL}" download="img.${ext}">Download</a>`;
    })
    .catch(console.error);
};

document.querySelector('#map2Png').addEventListener('click', _ => svgToImgDownload('png'));
document.querySelector('#map2Jpg').addEventListener('click', _ => svgToImgDownload('jpg'));
document.querySelector('#map2Webp').addEventListener('click', _ => svgToImgDownload('webp'));
<div id="svg_container" style="float: left; width: 50%">
  <svg width="200" height="200" viewBox="-100 -100 200 200">
    <circle cx="0" cy="20" r="70" fill="#D1495B" />
    <circle cx="0" cy="-75" r="12" fill="none" stroke="#F79257" stroke-width="2" />
    <rect x="-17.5" y="-65" width="35" height="20" fill="#F79257" />
  </svg>
</div>

<div>
  <button id="map2Png">PNG</button>
  <button id="map2Jpg">JPG</button>
  <button id="map2Webp">WEBP</button>
</div>

<div id="img_download_btn"></div>

评论

0赞 Ol Sen 2/28/2023
if (!['jpg'].includes(ext)) return如果有人使用 jpeg,则永远不会到达,猜你的意思是ext == 'jpg' ? 'jpeg'['png','jpg','jpeg','webp']
2赞 Carson 8/24/2022 #12
  1. 从 SVG 获取数据 URI

    data:image/svg+xml;base64,${btoa(new XMLSerializer().serializeToString(svgElem))}

  2. 准备镜像
  3. 创建一个画布,并使用 toDataURL 导出。

<!-- test data-->
<svg width="400" height="400"><g transform="translate(23.915343915343925,-80.03971756398937)" class="glyph" stroke="#000000" fill="#a0a0a0"><path d="M74.97 108.70L74.97 108.70L100.08 110.77Q93.89 147.91 87.35 179.89L87.35 179.89L148.23 179.89L148.23 194.34Q143.76 277.91 113.84 339.81L113.84 339.81Q144.44 363.54 163.70 382.46L163.70 382.46L146.51 402.75Q128.62 384.18 101.80 361.83L101.80 361.83Q75.32 405.85 34.39 436.80L34.39 436.80L17.20 415.82Q57.43 386.93 82.20 345.66L82.20 345.66Q57.78 326.40 27.86 304.39L27.86 304.39Q44.37 257.96 56.75 203.97L56.75 203.97L19.26 203.97L19.26 179.89L61.90 179.89Q69.47 145.16 74.97 108.70ZM93.20 323.99L93.20 323.99Q118.65 272.06 123.12 203.97L123.12 203.97L82.20 203.97Q69.47 260.03 55.71 297.17L55.71 297.17Q76.01 311.61 93.20 323.99ZM160.26 285.13L160.26 260.37L239.71 260.37L239.71 216.01Q268.25 191.24 294.05 155.48L294.05 155.48L170.58 155.48L170.58 130.71L322.94 130.71L322.94 155.48Q297.49 191.93 265.50 223.92L265.50 223.92L265.50 260.37L337.38 260.37L337.38 285.13L265.50 285.13L265.50 397.59Q265.50 431.64 237.65 431.64L237.65 431.64L187.09 431.64L180.21 407.57Q202.22 407.91 227.67 407.91L227.67 407.91Q239.71 407.91 239.71 390.03L239.71 390.03L239.71 285.13L160.26 285.13Z"></path></g></svg>

<button title="download">svg2png</button>
<script>
    const output = {"name": "result.png", "width": 64, "height": 64}
    document.querySelector("button").onclick = () => {
        const svgElem = document.querySelector("svg")
        // const uriData = `data:image/svg+xml;base64,${btoa(svgElem.outerHTML)}` // it may fail.
        const uriData = `data:image/svg+xml;base64,${btoa(new XMLSerializer().serializeToString(svgElem))}`
        const img = new Image()
        img.src = uriData
        img.onload = () => {
            const canvas = document.createElement("canvas");
            [canvas.width, canvas.height] = [output.width, output.height]
            const ctx = canvas.getContext("2d")
            ctx.drawImage(img, 0, 0, output.width, output.height)

            // 👇 download
            const a = document.createElement("a")
            const quality = 1.0 // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/imageSmoothingQuality
            a.href = canvas.toDataURL("image/png", quality)
            a.download = output.name
            a.append(canvas)
            a.click()
            a.remove()
        }
    }
</script>

29赞 Teocci 10/11/2022 #13

这是一个老问题,在 2022 年我们有 ES6,我们不需要第三方库。

这是将图像转换为其他格式的一种非常基本的方法。svg

诀窍是将元素加载为元素,然后使用 canvas 元素将图像转换为所需的格式。因此,需要四个步骤:svgimg

  1. 提取为数据字符串。svgxml
  2. 将数据字符串加载到元素中xmlimg
  3. 使用元素将元素转换为imgdataURLcanvas
  4. 将转换后的元素加载到新元素中dataURLimg

第 1 步

提取一个作为数据字符串很简单,我们不需要将其转换为 base64 字符串。我们只是将其序列化为 XML,然后将字符串编码为 URI:svgxml

// Data header for a svg image: 
const dataHeader = 'data:image/svg+xml;charset=utf-8'

// Serialize it as xml string:
const serializeAsXML = $e => (new XMLSerializer()).serializeToString($e)

// Encode URI data as UTF8 data:
const encodeAsUTF8 = s => `${dataHeader},${encodeURIComponent(s)}`

// Select the element:
const $svg = document.getElementById('svg-container').querySelector('svg')

// Encode it as a data string:
const svgData = encodeAsUTF8(serializeAsXML($svg))

注意:

如果需要 base64 数据,可以使用此选项:

...

// Encode URI data as base64 data:
const encodeAsB64 = s => `${dataHeader};base64,${btoa(s)}`
...

// Encode it as a data string:
const svgData = encodeAsB64(serializeAsXML($svg))

步骤 2

将数据字符串加载到元素中:xmlimg

// This function returns a Promise whenever the $img is loaded
const loadImage = async url => {
    const $img = document.createElement('img')
    $img.src = url
    return new Promise((resolve, reject) => {
        $img.onload = () => resolve($img)
        $img.onerror = reject
        $img.src = url
    })
}

步骤 3

使用元素将元素转换为:imgdataURLcanvas

const $canvas = document.createElement('canvas')
$canvas.width = $svg.clientWidth
$canvas.height = $svg.clientHeight
$canvas.getContext('2d').drawImage(img, 0, 0, $svg.clientWidth, $svg.clientHeight)
return $canvas.toDataURL(`image/${format}`, 1.0)

步骤 4

将转换后的元素加载到新元素中:dataURLimg

const $img = document.createElement('img')
$img.src = dataURL
$holder.appendChild($img)

这里有一个工作片段:

const dataHeader = 'data:image/svg+xml;charset=utf-8'
const $svg = document.getElementById('svg-container').querySelector('svg')
const $holder = document.getElementById('img-container')
const $label = document.getElementById('img-format')

const destroyChildren = $element => {
  while ($element.firstChild) {
    const $lastChild = $element.lastChild ?? false
    if ($lastChild) $element.removeChild($lastChild)
  }
}

const loadImage = async url => {
  const $img = document.createElement('img')
  $img.src = url
  return new Promise((resolve, reject) => {
    $img.onload = () => resolve($img)
    $img.onerror = reject
  })
}

const serializeAsXML = $e => (new XMLSerializer()).serializeToString($e)

const encodeAsUTF8 = s => `${dataHeader},${encodeURIComponent(s)}`
const encodeAsB64 = s => `${dataHeader};base64,${btoa(s)}`

const convertSVGtoImg = async e => {
  const $btn = e.target
  const format = $btn.dataset.format ?? 'png'
  $label.textContent = format

  destroyChildren($holder)

  const svgData = encodeAsUTF8(serializeAsXML($svg))

  const img = await loadImage(svgData)
  
  const $canvas = document.createElement('canvas')
  $canvas.width = $svg.clientWidth
  $canvas.height = $svg.clientHeight
  $canvas.getContext('2d').drawImage(img, 0, 0, $svg.clientWidth, $svg.clientHeight)
  
  const dataURL = await $canvas.toDataURL(`image/${format}`, 1.0)
  console.log(dataURL)
  
  const $img = document.createElement('img')
  $img.src = dataURL
  $holder.appendChild($img)
}

const buttons = [...document.querySelectorAll('[data-format]')]
for (const $btn of buttons) {
  $btn.onclick = convertSVGtoImg
}
.wrapper {
  display: flex;
  flex-flow: row nowrap;
  width: 100vw;
}

.images {
  display: flex;
  flex-flow: row nowrap;
  width: 70%;
}

.image {
  width: 50%;
  display: flex;
  flex-flow: row wrap;
  justify-content: center;
}

.label {
  width: 100%;
  text-align: center;
}
<div class="wrapper">
  <div class="item images">
    <div class="image left">
      <div class="label">svg</div>
      <div id="svg-container">
        <svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="200" height="200" viewBox="0 0 248 204">
  <path fill="#1d9bf0" d="M221.95 51.29c.15 2.17.15 4.34.15 6.53 0 66.73-50.8 143.69-143.69 143.69v-.04c-27.44.04-54.31-7.82-77.41-22.64 3.99.48 8 .72 12.02.73 22.74.02 44.83-7.61 62.72-21.66-21.61-.41-40.56-14.5-47.18-35.07 7.57 1.46 15.37 1.16 22.8-.87-23.56-4.76-40.51-25.46-40.51-49.5v-.64c7.02 3.91 14.88 6.08 22.92 6.32C11.58 63.31 4.74 33.79 18.14 10.71c25.64 31.55 63.47 50.73 104.08 52.76-4.07-17.54 1.49-35.92 14.61-48.25 20.34-19.12 52.33-18.14 71.45 2.19 11.31-2.23 22.15-6.38 32.07-12.26-3.77 11.69-11.66 21.62-22.2 27.93 10.01-1.18 19.79-3.86 29-7.95-6.78 10.16-15.32 19.01-25.2 26.16z"/>
</svg>
      </div>
    </div>
    <div class="image right">
      <div id="img-format" class="label"></div>
      <div id="img-container"></div>
    </div>
  </div>
  <div class="item buttons">
    <button id="btn-png" data-format="png">PNG</button>
    <button id="btn-jpg" data-format="jpeg">JPG</button>
    <button id="btn-webp" data-format="webp">WEBP</button>
  </div>
</div>

评论

0赞 kartsims 12/14/2022
在步骤 2 中,您设置了两次,我相信第二次就足够了img.src
0赞 Teocci 12/15/2022
静止图像中的图像包含我们使用画布将其转换为另一个图像的图像(即.png,jpeg,...)如果在您的情况下,这已经足够了。我为大家提供了一个完整的解决方案。step 2data:image/svg+xmlformatstep 2
0赞 Andhi Irawan 10/24/2023 #14

如果目标是通过浏览器将 SVG 文件转换为 PNG 图像文件,也许以下网站可以为那些需要它的人提供帮助:

https://mybyways.com/blog/convert-svg-to-png-using-your-browser

enter image description here

在此部分中输入 SVG 代码,然后单击“加载 SVG”按钮

enter image description here

将出现 SVG 图像的预览,可以通过按将 SVG 另存为 PNG 按钮下载或保存为 PNG 图像文件。