Reputation: 15
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
Upvotes: 0
Views: 56
Reputation: 16
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>
Upvotes: 0