I'm using Javascript to dynamically create a SVG element composed of several shapes. The objects are being created dynamically such as done in this fiddle
The onclick function call should change the fill from yellow to black and back, and though it seems straightforward, of course it isn't :)
function toggleFill() {
let w = document.getElementById("svgCircle1");
//let isYellow = w.getAttribute('fill') == 'yellow';
let isYellow = w.style.fill == 'yellow';
console.log("w> " + w);
console.log("fill> " + w.style.fill);
if (isYellow) {
//w.setAttribute('fill', 'black');
w.style.fill = "black";
} else {
//w.setAttribute('fill', 'yellow');
w.style.fill = "yellow";
}
}
function doDrawing(x, y, r) {
const svgNS = "http://www.w3.org/2000/svg";
let svg = document.querySelector("svg");
function drawCircle(cx, cy, r) {
let c = document.createElementNS(svgNS, "circle");
c.setAttribute("id", "svgCircle1");
c.setAttribute("class", "svgCircle");
c.setAttribute("cx", cx);
c.setAttribute("cy", cy);
c.setAttribute("r", r);
c.setAttribute("onclick", "toggleFill();");
return c;
}
g = document.createElementNS(svgNS, "g");
g.setAttribute("id", "svgG1");
g.appendChild(drawCircle(x, y, r));
svg.appendChild(g);
}
.svgCircle {
fill: yellow;
}
<button id="button1" onclick="doDrawing( 50, 50, 10 );">Draw</button>
<svg width="1000" height="400" id="drawing">
</svg>
The issue is that sometimes the style attribute will be empty, sometimes it will have the correct value and not update, and some rare times it will work.
If I remove the group, it executes correctly. I see the same behaviour with the style.fill attribute access as I do with the getAttribute method call.
I had thought that perhaps the class style was being reapplied to the object for some unbeknownst reason, but adding the classList.remove has not resolved the issue either.
I can work around this issue by inverting the if logic and using my knowledge of the initial color, then setting the variable to black if it fails to match. Once the initial JS setAttribute or style.fill is run, then code becomes reliable.
I'm certain there's something basic I've overlooked, I'd prefer to understand what I missed than rely on the work around.
In the event it's relevant I've been testing in Chrome.
Thanks!
You need to stick to one way of adding the fill -- either as an attribute or in CSS.
I also removed the id. Now I don't know the use case, but ids have to be unique and you where pointing to a specific id in your function. So, here I just have an event listener for the entire SVG.
document.querySelector("svg").addEventListener('click', e => {
let w = e.target;
if (w.nodeName == 'circle') {
let isYellow = w.style.fill == 'yellow';
console.log("w> " + w);
console.log("fill> " + w.style.fill);
if (isYellow) {
//w.setAttribute('fill', 'black');
w.style.fill = "black";
} else {
//w.setAttribute('fill', 'yellow');
w.style.fill = "yellow";
}
}
});
function doDrawing(x, y, r) {
const svgNS = "http://www.w3.org/2000/svg";
let svg = document.querySelector("svg");
function drawCircle(cx, cy, r) {
let c = document.createElementNS(svgNS, "circle");
c.setAttribute("class", "svgCircle");
c.setAttribute("cx", cx);
c.setAttribute("cy", cy);
c.setAttribute("r", r);
c.style.fill = "yellow";
return c;
}
g = document.createElementNS(svgNS, "g");
g.setAttribute("id", "svgG1");
g.appendChild(drawCircle(x, y, r));
svg.appendChild(g);
}
<button id="button1" onclick="doDrawing( 50, 50, 10 );">Draw</button>
<svg width="1000" height="400" id="drawing">
</svg>