使用 JavaScript 将 SVG 转换为 PNG

我过去一直使用 canvg 将 SVG 转换为 PNG,但是正如您从链接中看到的那样,它并不支持所有 SVG 功能。如果您使用 D3 或任何喜欢在 SVG 中工作的库,那么您可能会遇到一些不起作用的东西——在我的例子中是 textPath。

SVG 提供了沿任意路径绘制文本的功能,我需要在我的Chord Snip附加组件中执行此操作,但我没有任何方法可以获取生成的 SVG 并创建一个图像,Google Sheets 可以将其用作嵌入图像。
理想情况下,我想使用浏览器来呈现 SVG 而不是 canvg,然后以某种方式获取光栅化结果以从中制作 png 图像,然后将其传递给 Google 表格。就是这样。
 
Dom 有一个 API 方法来创建一个对象——createObjectURL(svgtext)。API 因浏览器而异,但这里介绍了如何找到它。
1
2
3
4
var domUrl = window.URL || window.webkitURL || window;
        if (!domUrl) {
          throw new Error("(browser doesnt support this)")
        }

这个想法是从 svg 代码创建该对象,将其加载到图像元素,然后将该图像写入画布。然后我们可以使用 toDataURL() 来制作一个 base64 编码的 PNG 图像,我们就完成了。
第一步是创建 url,但除非 svg 代码定义了其命名空间,否则这将失败,因此我们将戳 svg 代码
1
2
3
4
// it needs a namespace
        if (!svgText.match(/xmlns=\"/mi)){
          svgText = svgText.replace ('<svg ','<svg xmlns="http://www.w3.org/2000/svg" ') ;  
        }

做一个斑点
1
2
3
4
// make a blob from the svg
        var svg = new Blob([svgText], {
          type: "image/svg+xml;charset=utf-8"
        });

然后从 blob 创建 URL
1
var url = domUrl.createObjectURL(svg);

接下来我们需要一个画布,但我们需要通过在 svg 代码中挖掘来推断出所需的画布大小。
1
2
3
4
5
// figure out the height and width from svg text
        var match = svgText.match(/height=\"(\d+)/m);
        var height = match && match[1] ? parseInt(match[1],10) : 200;
        var match = svgText.match(/width=\"(\d+)/m);
        var width = match && match[1] ? parseInt(match[1],10) : 200;

现在我们可以创建一个画布元素来临时使用。我还将允许一些边距空间作为参数传递,因此画布需要足够大以容纳图像加上周围的任何填充。
1
2
3
4
5
// create a canvas element to pass through
        var canvas = document.createElement("canvas");
        canvas.width = height+margin*2;
        canvas.height = width+margin*2;
        var ctx = canvas.getContext("2d");

我需要一个新图像,当它加载时,我可以把它写到我的画布上。作为额外的一块糖,我将允许图像具有可选的背景填充 - 如果您有边距或透明输入,则很有用。如果它确实有一个,那么我需要第二个画布,可以用来设置第一个画布的样式。整个事情都包含在一个承诺中,因此可以通过传递 svg 图像的最终画布表示的 toDataUrl() 来解决它。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// create a new image to hold it the converted type
        var img = new Image;
        
        // when the image is loaded we can get it as base64 url
        img.onload = function() {
          // draw it to the canvas
          ctx.drawImage(this, margin, margin);
          
          // if it needs some styling, we need a new canvas
          if (fill) {
            var styled = document.createElement("canvas");
            styled.width = canvas.width;
            styled.height = canvas.height;
            var styledCtx = styled.getContext("2d");
            styledCtx.save();
            styledCtx.fillStyle = fill;  
            styledCtx.fillRect(0,0,canvas.width,canvas.height);
            styledCtx.strokeRect(0,0,canvas.width,canvas.height);
            styledCtx.restore();
            styledCtx.drawImage (canvas, 0,0);
            canvas = styled;
          }
          // we don't need the original any more
          domUrl.revokeObjectURL(url);
          // now we can resolve the promise, passing the base64 url
          resolve(canvas.toDataURL());
        };
        
        // load the image
        img.src = url;

整个东西都可以这样使用。
1
2
3
4
5
6
7
svgToPng (svgCode , marginSize, canvasFillColor)
.then (function(data) {
    // do something with the encode b64 image
})
.catch (function (err) {
  // do something with the error
});

编码

我会在试用时报告浏览器兼容性,或者如果您试用它们,请告诉我。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/**
  * converts an svg string to base64 png using the domUrl
  * @param {string} svgText the svgtext
  * @param {number} [margin=0] the width of the border - the image size will be height+margin by width+margin
  * @param {string} [fill] optionally backgrund canvas fill
  * @return {Promise} a promise to the bas64 png image
  */
  var svgToPng = function (svgText, margin,fill) {
    // convert an svg text to png using the browser
    return new Promise(function(resolve, reject) {
      try {
        // can use the domUrl function from the browser
        var domUrl = window.URL || window.webkitURL || window;
        if (!domUrl) {
          throw new Error("(browser doesnt support this)")
        }
        
        // figure out the height and width from svg text
        var match = svgText.match(/height=\"(\d+)/m);
        var height = match && match[1] ? parseInt(match[1],10) : 200;
        var match = svgText.match(/width=\"(\d+)/m);
        var width = match && match[1] ? parseInt(match[1],10) : 200;
        margin = margin || 0;
        
        // it needs a namespace
        if (!svgText.match(/xmlns=\"/mi)){
          svgText = svgText.replace ('<svg ','<svg xmlns="http://www.w3.org/2000/svg" ') ;  
        }
        
        // create a canvas element to pass through
        var canvas = document.createElement("canvas");
        canvas.width = height+margin*2;
        canvas.height = width+margin*2;
        var ctx = canvas.getContext("2d");
        
        
        // make a blob from the svg
        var svg = new Blob([svgText], {
          type: "image/svg+xml;charset=utf-8"
        });
        
        // create a dom object for that image
        var url = domUrl.createObjectURL(svg);
        
        // create a new image to hold it the converted type
        var img = new Image;
        
        // when the image is loaded we can get it as base64 url
        img.onload = function() {
          // draw it to the canvas
          ctx.drawImage(this, margin, margin);
          
          // if it needs some styling, we need a new canvas
          if (fill) {
            var styled = document.createElement("canvas");
            styled.width = canvas.width;
            styled.height = canvas.height;
            var styledCtx = styled.getContext("2d");
            styledCtx.save();
            styledCtx.fillStyle = fill;  
            styledCtx.fillRect(0,0,canvas.width,canvas.height);
            styledCtx.strokeRect(0,0,canvas.width,canvas.height);
            styledCtx.restore();
            styledCtx.drawImage (canvas, 0,0);
            canvas = styled;
          }
          // we don't need the original any more
          domUrl.revokeObjectURL(url);
          // now we can resolve the promise, passing the base64 url
          resolve(canvas.toDataURL());
        };
        
        // load the image
        img.src = url;
        
      } catch (err) {
        reject('failed to convert svg to png ' + err);
      }
    });
  };
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 可以使用node-canvas库将svg转换png。 安装: ``` npm install canvas ``` 示例代码: ``` const { createCanvas, loadImage } = require('canvas') const fs = require('fs') async function svg2png(svg, png) { const image = await loadImage(svg) const canvas = createCanvas(image.width, image.height) const ctx = canvas.getContext('2d') ctx.drawImage(image, 0, 0) const buffer = canvas.toBuffer() fs.writeFileSync(png, buffer) } svg2png('input.svg', 'output.png') ``` 此代码将“input.svg”文件转换为“output.png”文件。 ### 回答2: SVG是一种可伸缩矢量图形格式,而PNG是一种位图图像格式。如果我们想把SVG文件转换PNG,我们可以使用Node.js来完成。 首先,我们需要安装一些必要的Node.js库。我们可以使用`npm`命令来安装`svg2png`库,这个库可以帮助我们将SVG转换PNG。打开终端窗口,并输入以下命令来安装`svg2png`库: ``` npm install svg2png ``` 安装完成后,我们可以创建一个Node.js脚本来执行转换操作。在脚本中,我们首先需要引入`svg2png`库和`fs`库,`fs`库用于读取和写入文件。然后,我们可以使用`svg2png`库的`convert`方法来执行转换。下面是一个示例代码: ```javascript const fs = require('fs'); const svg2png = require('svg2png'); const svgFilePath = 'path_to_svg_file.svg'; const pngFilePath = 'path_to_output_png_file.png'; fs.readFile(svgFilePath, (err, data) => { if (err) throw err; svg2png(data) .then(buffer => { fs.writeFile(pngFilePath, buffer, (err) => { if (err) throw err; console.log('SVG转换PNG成功!'); }); }) .catch(error => { console.error('转换失败:', error); }); }); ``` 在上面的代码中,我们首先读取SVG文件,然后使用`svg2png`库的`convert`方法将SVG转换PNG。最后,我们将转换后的PNG图像数据写入到指定的输出文件中。完成后,我们会在控制台输出成功或失败的相关信息。 要使用上述代码进行转换,我们需要将`path_to_svg_file.svg`替换为SVG文件的实际路径,将`path_to_output_png_file.png`替换为要生成的PNG文件的实际路径。执行脚本后,我们将得到一个转换成功的PNG图像文件。 需要注意的是,由于`svg2png`库依赖于Cairo库,因此在使用此方法之前,我们需要确保已经在计算机上安装了Cairo库。 ### 回答3: 使用Node将SVG转换PNG可以通过使用一些库来实现。 首先,你需要安装`svg2png`库。你可以使用npm命令安装它:`npm install svg2png`。 安装完库后,你需要在项目中引入它:`const svg2png = require('svg2png');`。 接下来,你可以使用以下代码将SVG文件转换PNG: ```javascript const fs = require('fs'); fs.readFile('input.svg', (err, data) => { if (err) throw err; // 将SVG数据转换PNG文件 svg2png(data) .then(buffer => { fs.writeFile('output.png', buffer, err => { if (err) throw err; console.log('PNG文件已生成'); }); }) .catch(error => { console.error('转换失败:', error); }); }); ``` 上述代码中,我们首先使用`fs`模块来读取SVG文件的数据。然后,我们使用`svg2png`函数将SVG数据转换PNG格式的数据。最后,我们使用`fs.writeFile`方法将PNG数据写入文件。 请确保在运行上述代码前,你已经准备好了一份名为`input.svg`的SVG文件。一旦代码执行完成,你将会在项目中看到一个名为`output.png`的PNG文件。 这就是使用Node将SVG转换PNG的简单方法。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值