SVG 作为 SVG 的图像标签在与 sharp 一起使用时不起作用
SVG as SVG's image tag not working while using with sharp
我正在使用 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 来展示我尝试做的事情。基本上,我想使用 sharp 将此 SVG 转换为 png 文件,但 sharp 给我一个空的 png。
看起来sharp
对外部图片的处理不是很好
您可以尝试 "flatten" SVG,然后再将其传递给 sharp
。
快速而肮脏的实施
这很容易出错。理想情况下,您会使用 Cheerio
之类的东西来解析和修改 SVG 输入。
它也仅保留 x
、y
、width
、height
和 opacity
属性。其他属性需要进一步更改。
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.
检查工作代码(出于测试目的有点不同,因为它使用缓冲区而不是文件输出)
我正在使用 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 来展示我尝试做的事情。基本上,我想使用 sharp 将此 SVG 转换为 png 文件,但 sharp 给我一个空的 png。
看起来sharp
对外部图片的处理不是很好
您可以尝试 "flatten" SVG,然后再将其传递给 sharp
。
快速而肮脏的实施
这很容易出错。理想情况下,您会使用 Cheerio
之类的东西来解析和修改 SVG 输入。
它也仅保留 x
、y
、width
、height
和 opacity
属性。其他属性需要进一步更改。
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.
检查工作代码(出于测试目的有点不同,因为它使用缓冲区而不是文件输出)