so I have a style in the svg image and I am using that to change the fill using javascript with a random colors function and that works fine. but when I need the svg to be in png format after the color is changed, the changed colors colors are not retained for the PNG but the original colors are kept instead
<style type="text/css">
:root{
--back:#662D91;
--shadow:0.28;
--highlight:#F3B4AE;
--stomach:#EA8A82;
--lightHigh:#FEE9E5;
--lasso:#9B5D12;
--gloves:#29A6DE;--glovesStroke:#000674;--gloves2:#29A6DE;--gloves3:#1C7FC9;--gloves4:#1D7DC6;--gloves5:#1C7DC4;
--hatBelow:#DB8556;
--hatBelow2:#8A3C13;
--hatInner:#8C4017;
--hatInner2:#934A24;
--hatInner3:#9D5C3A;
--stripe:#8A7454;
--stripeEnd:#382000;
}
.st0{fill:var(--back);}
.st1{opacity:var(--shadow);}
.st2{fill:var(--highlight);}
.st3{fill:var(--stomach);}
.st4{fill:var(--lightHigh);}
.st5{fill:var(--lasso);}
.st6{filter:url(#Adobe_OpacityMaskFilter);}
.st7{filter:url(#Adobe_OpacityMaskFilter_1_);}
.st8{clip-path:url(#SVGID_3_);mask:url(#SVGID_4_);fill:url(#SVGID_5_);}
.st9{opacity:0.7;clip-path:url(#SVGID_3_);fill:url(#SVGID_6_);}
.st10{fill:url(#SVGID_10_);}
.st11{fill:#FFD2B3;}
.st12{fill:#EEBD9C;}
.st13{fill:#FFE3CE;}
.st14{fill:#AF7B6E;}
.st15{fill:var(--gloves);stroke:var(--glovesStroke);stroke-miterlimit:10;}
.st16{fill:var(--gloves2);}
.st17{fill:var(--gloves3);}
.st18{fill:var(--gloves4);}
.st19{fill:var(--gloves5);}
</style>
this is the style element in my svg and I am changing it using this
root.style.setProperty('--back',colors[0]);
the colors is an array of colors that I get my randomly making a color using a script in the svg help plz so this is how i am converting svg to png
<script>
var svgString = new XMLSerializer().serializeToString(document.querySelector('svg'));
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var DOMURL = self.URL||self.webkitURL||self;
var img = new Image();
var svg = new Blob([svgString],{type: "image/svg xml;charset=utf-8"});
var url = DOMURL.createObjectURL(svg);
img.onload = function(){
ctx.drawImage(img,0,0);
var png = canvas.toDataURL("image/png");
document.querySelector('#png-container').innerHTML = '<img src="' png '"/>';
DOMURL.revokeObjectURL(png);
};
img.src = url;
</script>
CodePudding user response:
Edit: Took a minute to thing about it, and it makes sense that it doesn't work. svg
blob only includes svg
tag contents and hence has no idea there's a CSS variable set on html
tag outside of it. Styles applied with :root
are defined within SVG, so when you yank it out of HTML context, I assume :root
points to the svg
tag itself.
Not sure why it works this way, but when using canvas CSS variables set on ancestors of svg
tag seem to be ignored. What you can do to fix this is set inline styles on either svg
tag itself or its children.
Here's a reproduction with a fix, don't mind changes to the JS code, it does the exact same thing yours does just but sets CSS variable on svg
tag instead of html
.
<!DOCTYPE html>
<html lang="en">
<head>
<title>SVG thingy</title>
</head>
<body>
<svg
viewBox="0 0 10 10"
xmlns="http://www.w3.org/2000/svg"
>
<style>
:root {
--color: red;
}
circle {
fill: var(--color);
}
</style>
<circle
cx="5"
cy="5"
r="4"
/>
</svg>
<canvas></canvas>
<div id="png-container"></div>
<script>
const root = document.documentElement; // html tag
// root.style.setProperty('--color', 'black'); // Doesn't work
const svgElement = document.querySelector('svg');
svgElement.style.setProperty('--color', 'black'); // Works
const svgString = new XMLSerializer().serializeToString(document.querySelector('svg'));
const svgBlob = new Blob([svgElement.outerHTML], { type: 'image/svg xml;charset=utf-8' });
const url = URL.createObjectURL(svgBlob);
const canvasElement = document.querySelector('canvas');
const ctx = canvasElement.getContext('2d');
const img = new Image();
img.src = url;
img.onload = () => {
ctx.drawImage(img, 0, 0);
const png = canvasElement.toDataURL('image/png');
document.querySelector('#png-container').innerHTML = '<img src="' png '"/>';
URL.revokeObjectURL(png);
};
</script>
</body>
</html>