You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

浏览器使用Canvas API转SVG为PNG时Safari嵌入式图片随机空白问题

问题原因
  • Safari加载包含内嵌资源的SVG时,load事件触发时机早于内部内嵌base64图片的解码完成时间,此时直接绘制SVG到canvas,就会出现内嵌图片区域空白的问题,随机性来自于不同场景下图片解码速度的差异
  • 部分版本Safari对SVG的xlink:href属性支持不稳定,该属性已被SVG标准废弃,推荐使用标准href属性替代
解决方案
  1. 预处理SVG字符串,为所有<image>标签同时补充href属性,值和xlink:href完全一致
  2. 调整SVG加载逻辑,触发onload后额外等待一到两个浏览器渲染帧,确保内部资源完全解码后再执行绘制操作
  3. 绘制完成后及时释放创建的Blob URL避免内存泄漏

修改后可兼容Safari的参考代码如下:

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)

// 预处理SVG:给image标签补充标准href属性
const processedSvg = rawSvgString.replace(/<image([^>]+)xlink:href="([^"]+)"([^>]*)>/g, '<image$1xlink:href="$2" href="$2"$3>')

let img = new Image()
let svgBlob = new Blob([processedSvg], { type: 'image/svg+xml' })
let svgUrl = URL.createObjectURL(svgBlob)

img.onload = function () {
    // 等待2个渲染帧确保Safari完成内部资源解码
    requestAnimationFrame(() => {
        requestAnimationFrame(() => {
            ctx.drawImage(img, 0, 0, width, height, padding, 0, width, height)

            canvas.toBlob((blob) => {
                saveAs(blob, 'image.png')
                // 释放占用的内存
                URL.revokeObjectURL(svgUrl)
            })
        })
    })
}

img.src = svgUrl

如果仍有偶现空白问题,可将Blob URL替换为base64格式的Data URL进一步提升兼容性:
把img.src = svgUrl替换为img.src = 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(processedSvg)即可。

内容的提问来源于stack exchange,提问作者Ivan Bacher

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 08:45:03