在使用canvas api在浏览器中将svg转换为png时,svg中的嵌入图像在Safari中随机空白

Posted

技术标签:

【中文标题】在使用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 【发布时间】:2021-12-08 19:41:56 【问题描述】:

我正在使用下面的代码从有效的 svg 字符串创建一个 png。 svg 中有一个嵌入的图像。

<image xlink:href="data:image/png;base64,..." x="0" y="0"  />

这在 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' ))

【问题讨论】:

【参考方案1】:

这是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"   viewBox="0 0 100 100">
    <rect   fill="purple"/>
    <image href="$ png_dataURL + anti_cache "  />
  </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);
    
  );
&lt;canvas&gt;&lt;/canvas&gt;

【讨论】:

以上是关于在使用canvas api在浏览器中将svg转换为png时,svg中的嵌入图像在Safari中随机空白的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 或 C++ 中将 ms word 文档转换为 svg

D3系列06-canvas和SVG的比较

如何在 C# 中将 SVG 文件转换为 EMF 文件

坎夫 |将 SVG 转换为 Canvas 以输出为图像

浏览器端绘图技术SVG VML Canvas WebGL介绍

如何在ghostscript中将svg、eps和ai转换为png