I have an svg/xml file that I'm loading into d3 using d3.xml(...)
This is the output of the SVG
I also have a small JSON dataset
const data = [{
"id": "polygon5256", //roof
"value": 39.5
},
{
"id": "polygon1628", //grass
"value": 3.93
},
{
"id": "polygon5254", //left wall
"value": 3.14
},
{
"id": "path5894", //door step
"value": 20.98
}
]
I'm trying to join the id's from the JSON dataset to the respective id's (polygons and paths) in the XML data.
Here is my jsfiddle
Any help would be much appreciated
CodePudding user response:
In your fiddle you have d3.select('#polygon5256')
but you can add events to any polygon with selectAll
and a different CSS selector:
d3.selectAll("svg polygon")
You want path
too (for the door step) so the CSS selector you need is:
d3.selectAll("svg polygon, svg path")
In the handler you can get the id
of the polygon with (since you use d3 v5.9.2):
d3.event.target.id
Note that if you're using a later version of the D3 library this handling will need to change (see D3 v6 changes)
I've changed your fiddle to have a single visible div
where the mouseover and mouseout handlers just populate labelling if available in data
or clear the text.
Working example:
const data = [
{ "id": "polygon5256", "value": 39.5 }, // roof
{ "id": "polygon1628", "value": 3.93 }, // grass
{ "id": "polygon5254", "value": 3.14 }, // left wall
{ "id": "path5894", "value": 20.98 } // door step
];
// just make one visible div and leave text till later
const tooltip = d3.select("body")
.append("div")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "visible");
const svgUrl = "https://raw.githubusercontent.com/gangrel11/samplefiles/main/house.svg";
d3.xml(svgUrl).then(render);
// on render set an event for any polygon of the svg
function render(data) {
d3.select("body").node().append(data.documentElement)
d3.selectAll("svg polygon, svg path")
.on("mouseover", mouseover)
.on("mouseout", mouseout);
}
// set the text of the div if it's in the data set
function mouseover(d) {
const id = d3.event.target.id;
const obj = data.find(item => item.id === id);
const text = obj ? `${id} - ${obj.value}` : "";
tooltip.text(text);
d3.select(`#${id}`).style("opacity", 0.5);
}
// clear the text of the div
function mouseout(d) {
const id = d3.event.target.id;
tooltip.text("");
d3.select(`#${id}`).style("opacity", 1);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>