ARTICLE AD BOX
This seems to be an issue with the hardware accelerated renderer.
You can file an issue at https://bugzilla.mozilla.org/enter_bug.cgi
For a workaround, you can force your 2D context to use software rendering by passing the willReadFrequently: true option in the getContext() call.
async function svg_to_canvas(svg_el, canvas) {
// svg to blob URL
const serializer = new XMLSerializer();
const source = serializer.serializeToString(svg_el);
const svg_blob = new Blob([source], {
type: "image/svg+xml;charset=utf-8"
});
const svg_url = URL.createObjectURL(svg_blob);
// convert blob URL to image
const img = new Image();
await new Promise((resolve, reject) => {
img.onload = () => resolve(createImageBitmap(img));
img.onerror = (err) => reject(err);
img.src = svg_url;
})
// then paint on canvas
const ratio = window.devicePixelRatio;
canvas.setAttribute('width', svg_el.getAttribute("width") * ratio);
canvas.setAttribute('height', svg_el.getAttribute("height") * ratio);
canvas.style.width = svg_el.getAttribute("width") + "px";
const context = canvas.getContext('2d', { willReadFrequently: true });
context.imageSmoothingQuality = "high";
context.drawImage(img, 0, 0, canvas.width, canvas.height);
}
svg_to_canvas(document.getElementById("test-svg"), document.getElementById('test-canvas'));
<p>SVG:</p>
<!-- The below is an SVG with many triangles, filling up a large triangle -->
<svg id="test-svg" width="400" height="200" style="display: block; outline: 1px solid silver;">
<rect x="5.5" y="5.5" width="99" height="99" fill="#ddd" stroke="black"/>
<g shape-rendering="crispEdges"><path d="M 56.0 18.0 L 47.2 33.2 L 64.8 33.2 Z" fill="rgb(237.41034097107058, 65.8077882928761, 65.8077882928761)" stroke-width="none" stroke="none"></path><path d="M 47.2 33.2 L 64.8 33.2 L 56.0 48.4 Z" fill="rgb(218.40072063744432, 93.07557473646084, 93.07557473646084)" stroke-width="none" stroke="none"></path><path d="M 64.8 33.2 L 56.0 48.4 L 73.6 48.4 Z" fill="rgb(208.22744775845476, 65.8077882928761, 131.664972562941)" stroke-width="none" stroke="none"></path><path d="M 56.0 48.4 L 73.6 48.4 L 64.8 63.6 Z" fill="rgb(186.25593481725875, 93.07557473646082, 147.20959252992503)" stroke-width="none" stroke="none"></path><path d="M 73.6 48.4 L 64.8 63.6 L 82.3 63.6 Z" fill="rgb(174.22304669589496, 65.8077882928761, 174.18571985096827)" stroke-width="none" stroke="none"></path><path d="M 64.8 63.6 L 82.3 63.6 L 73.6 78.8 Z" fill="rgb(147.25376645215857, 93.07557473646084, 186.2210129204828)" stroke-width="none" stroke="none"></path><path d="M 82.3 63.6 L 73.6 78.8 L 91.1 78.8 Z" fill="rgb(131.71435001547857, 65.8077882928761, 208.19621754489202)" stroke-width="none" stroke="none"></path><path d="M 73.6 78.8 L 91.1 78.8 L 82.3 94.0 Z" fill="rgb(93.14542508380538, 93.07557473646084, 218.37093939770165)" stroke-width="none" stroke="none"></path><path d="M 91.1 78.8 L 82.3 94.0 L 99.9 94.0 Z" fill="rgb(65.9065247149324, 65.8077882928761, 237.3829501038354)" stroke-width="none" stroke="none"></path><path d="M 47.2 33.2 L 38.4 48.4 L 56.0 48.4 Z" fill="rgb(208.22744775845476, 131.664972562941, 65.8077882928761)" stroke-width="none" stroke="none"></path><path d="M 38.4 48.4 L 56.0 48.4 L 47.2 63.6 Z" fill="rgb(186.25593481725875, 147.20959252992503, 93.07557473646082)" stroke-width="none" stroke="none"></path><path d="M 56.0 48.4 L 47.2 63.6 L 64.8 63.6 Z" fill="rgb(174.223046695895, 131.664972562941, 131.664972562941)" stroke-width="none" stroke="none"></path><path d="M 47.2 63.6 L 64.8 63.6 L 56.0 78.8 Z" fill="rgb(147.2537664521586, 147.20959252992503, 147.20959252992503)" stroke-width="none" stroke="none"></path><path d="M 64.8 63.6 L 56.0 78.8 L 73.6 78.8 Z" fill="rgb(131.7143500154786, 131.664972562941, 174.18571985096827)" stroke-width="none" stroke="none"></path><path d="M 56.0 78.8 L 73.6 78.8 L 64.8 94.0 Z" fill="rgb(93.14542508380542, 147.20959252992506, 186.2210129204828)" stroke-width="none" stroke="none"></path><path d="M 73.6 78.8 L 64.8 94.0 L 82.3 94.0 Z" fill="rgb(65.9065247149324, 131.664972562941, 208.19621754489202)" stroke-width="none" stroke="none"></path><path d="M 38.4 48.4 L 29.7 63.6 L 47.2 63.6 Z" fill="rgb(174.22304669589496, 174.18571985096827, 65.8077882928761)" stroke-width="none" stroke="none"></path><path d="M 29.7 63.6 L 47.2 63.6 L 38.4 78.8 Z" fill="rgb(147.25376645215857, 186.2210129204828, 93.07557473646084)" stroke-width="none" stroke="none"></path><path d="M 47.2 63.6 L 38.4 78.8 L 56.0 78.8 Z" fill="rgb(131.71435001547857, 174.18571985096827, 131.664972562941)" stroke-width="none" stroke="none"></path><path d="M 38.4 78.8 L 56.0 78.8 L 47.2 94.0 Z" fill="rgb(93.1454250838054, 186.2210129204828, 147.20959252992506)" stroke-width="none" stroke="none"></path><path d="M 56.0 78.8 L 47.2 94.0 L 64.8 94.0 Z" fill="rgb(65.9065247149324, 174.18571985096827, 174.18571985096827)" stroke-width="none" stroke="none"></path><path d="M 29.7 63.6 L 20.9 78.8 L 38.4 78.8 Z" fill="rgb(131.71435001547857, 208.19621754489202, 65.8077882928761)" stroke-width="none" stroke="none"></path><path d="M 20.9 78.8 L 38.4 78.8 L 29.7 94.0 Z" fill="rgb(93.14542508380538, 218.37093939770165, 93.07557473646084)" stroke-width="none" stroke="none"></path><path d="M 38.4 78.8 L 29.7 94.0 L 47.2 94.0 Z" fill="rgb(65.90652471493237, 208.19621754489202, 131.664972562941)" stroke-width="none" stroke="none"></path><path d="M 20.9 78.8 L 12.1 94.0 L 29.7 94.0 Z" fill="rgb(65.9065247149324, 237.3829501038354, 65.8077882928761)" stroke-width="none" stroke="none"></path></g>
</svg>
<p>Canvas:</p>
<canvas id="test-canvas" style="display: block; margin-bottom: 1em; outline: 1px solid silver;"></canvas>

