Estoy usando el siguiente código para crear un png a partir de una cadena svg válida. El svg tiene una imagen incrustada dentro de él.
<image xlink:href="data:image/png;base64,..." x="0" y="0" width="362" height="234"/>Esto funciona bien en Chrome y Firefox, pero tengo este comportamiento extraño en Safari y Safari Mobile. La imagen incrustada a veces está en blanco. El diseño sigue respetando las dimensiones de la imagen, pero se muestra en blanco. El resto del svg todavía funciona bien.
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' }))Este es un error conocido y antiguo .
Para una solución alternativa, parece que un simple setTimeout(draw, 100) es suficiente, aunque parece bastante frágil para ser honesto (por ejemplo, 0 estaba trabajando con mi imagen pero no con el ejemplo de fuente en el informe de errores).
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>