【问题标题】:SVG as SVG's image tag not working while using with sharpSVG作为SVG的图像标签在使用sharp时不起作用
【发布时间】:2020-02-12 23:10:48
【问题描述】:

我正在使用sharp 转换文件,但Sharp 给了我一个空的png 文件。

我想使用 base64 格式的 SVG 图像作为<image> 标签的来源,并希望将其转换为 png 文件。

这里有一个例子来展示我正在尝试做的事情;

const sharp = require('sharp');
sharp(Buffer.from(<look below js file to see the SVG>))
    .toFormat('png')
    .toFile('output.png')

这里有一个JS 来展示我尝试做的事情。基本上,我想将这个 SVG 转换为一个 png 文件,使用 sharp 但 sharp 给了我一个空的 png。

【问题讨论】:

  • 您链接到的小提琴不包含任何 JavaScript 代码。只有带有单个 SVG 的 HTML,它实际上只是作为带有数据 URI 的 IMAGE 元素嵌入其中的另一个 SVG 的包装器。
  • @ahwayakchih 是的,sharp 不会使用此输入创建 png 文件。那是我的问题

标签: node.js image svg sharp


【解决方案1】:

看起来sharp 不能很好地处理外部图像。

您可以在将 SVG 传递给 sharp 之前尝试“扁平化”它。

快速而肮脏的实现

这很容易出错。理想情况下,您会使用 Cheerio 之类的东西来解析和修改 SVG 输入。

它还仅保留 xywidthheightopacity 属性。其他属性需要进一步更改。

function flattenSVG (svg) {
  const images = svg.match(/<image [^>]+>/g);
  if (!images || images.length < 1) {
    return svg;
  }

  var result = svg;
  images.forEach(image => {
    const [,data] = image.match(/ xlink:href="data:image\/svg\+xml;base64,([^"]+)"/) || [];
    if (!data) {
      return;
    }

    const innerSVG = Buffer.from(data, 'base64').toString();
    const [,width] = image.match(/ width="([^"]+)"/) || [];
    const [,height] = image.match(/ height="([^"]+)"/) || [];
    const [,opacity] = image.match(/ opacity="([^"]+)"/) || [];
    const [,x] = image.match(/ x="([^"]+)"/) || [];
    const [,y] = image.match(/ y="([^"]+)"/) || [];
    const [header] = innerSVG && innerSVG.match(/<svg[^>]+>/) || [];
    const fixedHeader = header
      .replace(/ (x|y|width|height)="([^"]+)"/g, '')
      .replace('<svg', `<svg x="${x}" y="${y}" width="${width}" height="${height}" opacity="${opacity || 1.0}"`);
    const replacement = innerSVG && innerSVG.replace(header, fixedHeader);
    result = result.replace(image, replacement);
  });

  return result;
}

所以,在你的代码中,你会使用类似的东西:

sharp(Buffer.from(flattenSVG(testSVG)))
      .toFormat('png')
      .toFile('output.png')

您可以在Glitch 处检查工作代码(出于测试目的,它使用缓冲区而不是文件输出,因此略有不同)。

【讨论】:

  • 非常感谢您的努力,这就是我一直在寻找的答案,但我认为如果我将 SVG 转换为 PNG,它会容易得多。不过谢谢。
  • 您是指以其他方式转换为 PNG 吗?因为上面的代码确实创建了 PNG 文件。只是 Glitch 上的示例代码将其保留在 Buffer 中(数据仍然是 PNG 内容,只是没有写入文件)。
  • 是的,我已经阅读了您的代码。我有编码的 SVG 图像文件,所以我将直接将其转换为 PNG,然后我将在另一个 SVG 模板中使用 PNG,但如果出现性能问题,我会尝试你的答案。再次感谢!
  • 嗯.. 为什么需要在 SVG 中嵌入 PNG?这很丑陋,并且错过了 SVG(Scalable Vector :) 的要点之一。
  • 没错!但是这种方式对我们来说很容易。我们正在处理复杂的图像,我们没有太多时间。所以对于第一个版本,我们将使用 PNG 图像。目前,我们的目标不是完美的编码。在我们发布我们的产品之后,我们将启动我们产品的第二个版本,我们会将所有 PNG 图像转换为 SVG 图像,我将使用您的答案。当我们开始工作 V2 时,如果您的方法有问题,我会通知您。
猜你喜欢
  • 2012-06-21
  • 2023-01-21
  • 2015-04-29
  • 2020-07-13
  • 2016-08-04
  • 2019-11-22
  • 2017-09-13
  • 2016-06-09
  • 2016-07-30
相关资源
最近更新 更多