I'm using Svelte, I trying to convert a SVG to an image and download it. This is my app screen ->
The SVG is rendering properly except the logo at the center. I'm using canvas to get SVG to image and draw logo at the center. As you can see in the below image, everything is fine but there is a broken image artifact at the center. This only happen after i ran build and preview not in local while I develop.
Additional note that this happen on any other browser but not on safari.
here is the function
const downloadAsJpeg = () => {
if (!qrSvg) return;
const canvas = document.createElement('canvas');
canvas.width = 1000;
canvas.height = 1000;
const ctx = canvas.getContext('2d');
if (ctx) {
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, canvas.width, canvas.height);
const svgString = new XMLSerializer().serializeToString(qrSvg);
const svgBlob = new Blob([svgString], { type: 'image/svg+xml;charset=utf-8' });
const svgUrl = URL.createObjectURL(svgBlob);
const img = new Image();
img.onload = () => {
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
const logo = new Image();
logo.onload = () => {
const logoSize = 250;
const logoX = (canvas.width - logoSize) / 2;
const logoY = (canvas.height - logoSize) / 2;
ctx.drawImage(logo, logoX, logoY, logoSize, logoSize);
const jpegDataUrl = canvas.toDataURL('image/jpeg', 0.9);
const link = document.createElement('a');
link.href = jpegDataUrl;
link.download = `just-type-${scanToChatPhoneNumber}.jpeg`;
link.click();
URL.revokeObjectURL(svgUrl);
};
logo.src = logoLight;
};
img.src = svgUrl;
} else {
console.error('Failed to get 2d context from canvas.');
}
};
I try to remove the logo as i though maybe the path is incorrect after build but the issue is still there.
You can try to visit https://just-type.com to get the idea
I don't know the full code. So not sure how you are getting the qrSvg
value. But looking at the linked page I can tell that the issue is coming from the inner logo svg image.
<svg id="svg" viewBox="0, 0 39 39" xmlns="http://www.w3.org/2000/svg" version="1.1">
<g class="anchors">
...
<image width="8.8" height="8.8" x="15.6" y="15.6" href="https://just-type.com/_app/immutable/assets/logo_transparent_background._ckn0n7w.svg" class="logo"></image>
</svg>
The image
element inside the <svg>
tag is referencing an external url. When you convert this svg to serialized string and then blob, this external link remains as it is. So it will not be fetched when you draw it onto the Canvas.
Solution
Since in your script you are exclusively drawing the logo on the Canvas, you can remove the inner image
element from the svg before drawing it.
const qrSvg = document.getElementById('svg').cloneNode(true);
qrSvg.removeChild(qrSvg.getElementsByTagName('image')[0]);
Again not sure, how you are getting the qrSvg
. I'm just showing an example here.
Alternative option is to convert the external logo to a blob image and use it.
Checkout this JsFiddle Demo. In this demo I've given two buttons: one for reproducing the issue and one a solution for it.