Im trying to load an svg to canvas and it works great on chrome and firefox but it mess's up on webkit. I tried changing where the 3d transform but to no avail. Anyone have any experience or suggestions on how to fix?
Please find below a reduced test to verify the issue. Webkit Bug: https://bugs.webkit.org/show_bug.cgi?id=273939
Thanks slyi
const svgString = document.querySelector("#input_svg").value;
const div = document.createElement("div");
div.innerHTML = svgString;
const svgs = div.querySelectorAll("svg");
const convertButton = document.querySelector("#btn_convert");
const imageTest = document.querySelector("#imageTest");
const canvasTest = document.querySelector("#canvasTest");
imageTest.innerHTML=svgString;
const img = document.createElement("img");
const canvas = document.createElement("canvas");
const ctx = canvas.getContext('2d');
const URL = window.URL || window.webkitURL || window;
convertButton.onclick = async () => {
var imageSrc = await svgToBase64(svgs[0]);
canvasTest.src=imageSrc;
};
async function svgToBase64(svg) {
const width = svg.getAttribute("width");
const height = svg.getAttribute("height");
canvas.width = width;
canvas.height = height;
const data = new XMLSerializer().serializeToString(svg);
console.log(data)
const blob = new Blob([data], {
type: 'image/svg+xml'
});
console.log(blob)
var url = URL.createObjectURL(blob);
return new Promise((resolve) => {
img.onload = () => {
ctx.drawImage(img, 0, 0);
URL.revokeObjectURL(url);
resolve(canvas.toDataURL("image/png"));
}
img.src = url;
});
}
body {
background: #fff;
}
<h1>Webkit: SVG to Canvas lost transform3d</h1>
<br />
<div >
<div id="imageTest" />
<br/>
</div>
<button id="btn_convert">Convert SVG to canvas PNG </button>
<br />
<br />
<img id="canvasTest" />
<textarea id="input_svg" style="visibility:collapse;">
<svg version= "1.1" xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200" id="chess">
<defs>
<style>
#chess {
transform:perspective(500px) rotateX(65deg) ;
}
.chessPattern {
fill: red;
}
</style>
<pattern id="pattern-chess" x="0" y="0" width="40" height="40" patternUnits="userSpaceOnUse" >
<rect class="chessPattern" x="0" width="20" height="20" y="0" />
<rect class="chessPattern" x="20" width="20" height="20" y="20" />
</pattern>
</defs>
<g id="group" >
<rect width="200" height="200" fill="url(#pattern-chess)" />
</g>
</svg>
</textarea>
the css transform3d is lost on webkit
This webkit issue can be simplified by just inlining the image. CSS3 perspective is not supported in SVG, according to the webkit bug https://bugs.webkit.org/show_bug.cgi?id=273939
Simon Fraser (smfr) 2024-05-09 10:44:31 PDT WebKit doesn't support 3d transform functions in "flattened" drawing (e.g. into canvas). Our underlying graphics frameworks don't support this.
<div style="width: 400; overflow: hidden;position: absolute;top: -150px; left:0px" >
<div style="position: absolute;top: 175px;" >inline svg</div>
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="400" viewBox="0 0 400 400" style="transform:perspective(220px) rotateX(87deg) " >
<defs>
<pattern id="pattern-chess" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
<path d="M0 0h10v10H0zM10 10h10v10H10z"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="url(#pattern-chess)"/>
</svg>
</div>
<div style="overflow: hidden;width: 400; position: absolute;top: -150px; left:450px" >
<div style="position: absolute;top: 175px;">img svg</div>
<img src='data:image/svg+xml;utf8,
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="400" style="transform:perspective(220px) rotateX(87deg);" >
<defs>
<pattern id="pattern-chess" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
<path d="M0 0h10v10H0zM10 10h10v10H10z"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="url(%23pattern-chess)"/>
</svg> '/>
</div>