使用 canvas api 在浏览器中将 svg 转换为 png 时,svg 中的嵌入图像在 Safari 中随机空白
When converting an svg to png in the browser using canvas api, embedded image in svg is randomly blank in Safari
我正在使用下面的代码从有效的 svg 字符串创建 png。 svg 中有一个嵌入的图像。
<image xlink:href="data:image/png;base64,..." x="0" y="0" width="362" height="234"/>
这在 chrome 和 firefox 中工作正常,但我在 safari 和 safari mobile 中遇到这种奇怪的行为。嵌入的图像有时是空白的。布局仍然遵循图像的尺寸,但呈现为空白。其余的 svg 仍然可以正常渲染。
let canvas = document.createElement('canvas')
let ctx = canvas.getContext('2d')
canvas.width = width
canvas.height = height
ctx.fillStyle = 'white'
ctx.fillRect(0, 0, width, height)
let img = new Image()
img.onload = function () {
ctx.drawImage(img, 0, 0, width, height, padding, 0, width, height)
canvas.toBlob((blob) => {
saveAs(blob, 'image.png')
})
}
img.src = URL.createObjectURL(new Blob([rawSvgString], { type: 'image/svg+xml' }))
这是一个known and old bug。
对于解决方法,似乎一个简单的 setTimeout(draw, 100)
就足够了,尽管说实话这似乎很脆弱(例如 0
正在使用我的图像,但不适用于中的字体示例错误报告)。
const ctx = document.querySelector("canvas").getContext("2d");
(async () => {
const png_blob = await fetch("https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png").then(r=>r.ok&&r.blob());
const png_dataURL = await readAsDataURL(png_blob);
const anti_cache = "#" + Math.random();
const svg_markup = `<svg xmlns="http://www.w3.org/2000/svg" width="300" height="150" viewBox="0 0 100 100">
<rect width="10" height="10" fill="purple"/>
<image href="${ png_dataURL + anti_cache }" width="100" height="100"/>
</svg>`;
const svg_blob = new Blob([svg_markup], { type: "image/svg+xml" });
const img = new Image();
img.src = URL.createObjectURL(svg_blob);
img.onload = (evt) => {
setTimeout(
() => ctx.drawImage(img, 0, 0),
100
);
};
})().catch(console.error);
function readAsDataURL(blob) {
const reader = new FileReader();
return new Promise((res, rej) => {
reader.onload = () => res(reader.result);
reader.onerror = rej;
try {
reader.readAsDataURL(blob);
}
catch(err) {
rej(err);
}
});
}
<canvas></canvas>
我正在使用下面的代码从有效的 svg 字符串创建 png。 svg 中有一个嵌入的图像。
<image xlink:href="data:image/png;base64,..." x="0" y="0" width="362" height="234"/>
这在 chrome 和 firefox 中工作正常,但我在 safari 和 safari mobile 中遇到这种奇怪的行为。嵌入的图像有时是空白的。布局仍然遵循图像的尺寸,但呈现为空白。其余的 svg 仍然可以正常渲染。
let canvas = document.createElement('canvas')
let ctx = canvas.getContext('2d')
canvas.width = width
canvas.height = height
ctx.fillStyle = 'white'
ctx.fillRect(0, 0, width, height)
let img = new Image()
img.onload = function () {
ctx.drawImage(img, 0, 0, width, height, padding, 0, width, height)
canvas.toBlob((blob) => {
saveAs(blob, 'image.png')
})
}
img.src = URL.createObjectURL(new Blob([rawSvgString], { type: 'image/svg+xml' }))
这是一个known and old bug。
对于解决方法,似乎一个简单的 setTimeout(draw, 100)
就足够了,尽管说实话这似乎很脆弱(例如 0
正在使用我的图像,但不适用于中的字体示例错误报告)。
const ctx = document.querySelector("canvas").getContext("2d");
(async () => {
const png_blob = await fetch("https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png").then(r=>r.ok&&r.blob());
const png_dataURL = await readAsDataURL(png_blob);
const anti_cache = "#" + Math.random();
const svg_markup = `<svg xmlns="http://www.w3.org/2000/svg" width="300" height="150" viewBox="0 0 100 100">
<rect width="10" height="10" fill="purple"/>
<image href="${ png_dataURL + anti_cache }" width="100" height="100"/>
</svg>`;
const svg_blob = new Blob([svg_markup], { type: "image/svg+xml" });
const img = new Image();
img.src = URL.createObjectURL(svg_blob);
img.onload = (evt) => {
setTimeout(
() => ctx.drawImage(img, 0, 0),
100
);
};
})().catch(console.error);
function readAsDataURL(blob) {
const reader = new FileReader();
return new Promise((res, rej) => {
reader.onload = () => res(reader.result);
reader.onerror = rej;
try {
reader.readAsDataURL(blob);
}
catch(err) {
rej(err);
}
});
}
<canvas></canvas>