Reputation: 349
I am working on this pie-chart. This is what I would like to happen as the user clicks on a wedge of the pie:
1) An external svg is loaded and inserted in the div on the right (DONE)
1.1) The svg has the following structure
<svg id="Ebene_1">
<circle></circle>
<path></path>
<svg>
2) Change circle
's fill according to a color()
function which assign a color depending on the wedge's index
2) Change path
's fill to white
This is the relevant code I have so far:
descrImg = d3.select("#descrImg"); //select the target div
descrImg.select("svg").remove(); //removes previous image
descrImgURI = d.data.descrImg; //extract svg's URI from data
d3.xml(descrImgURI, "image/svg+xml", function(error, xml) {
if (error) throw error;
var svg= xml.documentElement;
descrImg.node().appendChild(svg); //append svg
var a = document.getElementById("Ebene_1"); //select svg
var b = a.getElementsByTagName("cicle"); //select circle
var c = a.getElementsByTagName("path"); //select path
d3.select(c).attr("fill", "white"); //change path's fill attribute
});
When I click on a wedge, the svg is loaded correctly but the path's fill is not changed. I get the following error (same happens if I use style
instead of attr
):
TypeError: this.setAttribute is not a function
Other options:
//Option 1
var c = d3.select(document.getElementById("#Ebene_1").contentDocument).selectAll("path");
d3.select(c).attr("fill", "yellow");
//Option 2
var c = d3.select(document.getElementById("Ebene_1").contentDocument).selectAll("path");
d3.select(c).attr("fill", "yellow");
//Both return the error
TypeError: document.getElementById(...) is null
//while Option 3
var c = document.getElementById("Ebene_1").contentDocument.getElementsByTagName("path");
d3.select(c).attr("fill", "yellow");
//Returns
TypeError: document.getElementById(...).contentDocument is undefined
I do not know if this matters, but when I inspect circle or fill I see their attributes are "locked" (a bit hard to see but there is a lock next to attributes)
Any ideas?
Upvotes: 0
Views: 1041
Reputation: 349
I have managed to solve the problem. This is the code that works:
d3.xml(descrImgURI, "image/svg+xml", function(error, xml) {
if (error) throw error;
var svg= xml.documentElement;
descrImg.node().appendChild(svg);
var a = document.getElementById("Ebene_1");
var b = a.getElementsByTagName("circle")[0];
var c = a.getElementsByTagName("path");
// d3.select(b).attr("fill", function (d, i) {
// var scale = colorMap[d.data.categoria];
// if (scale) return scale(d.data.catIndex);
// })
d3.select(b).attr("fill", fillColor);
d3.selectAll(c).attr("fill", "white");
});
getElementsByTagName returns a collection of items, regardless of how many items will be in the collection.
Therefore, in the case of b (i.e. the circle) I had to select the first element of the connection (through index [0]
).
The path(s) in c, on the other hand, can be collectively modified by using d3.selectAll
. If I use the same method as with b, then only the first set of paths would be modified and, at least in my case, this would leave some drawings partly uncolored.
Hope this helps!
Upvotes: 2