I am new to d3js and I want to create the following SVG from a JSON file. I am using d3js version 5.16.
<svg width="1024" height="700">
<g id="gp_node1">
<rect x="0" y="50" width="1024" height="10" id="node1"></rect>
<g id="gm_node1">
<circle cy="200" r="10" id="node1"></circle>
<text x="0" y="10" id="textnode1">node1</text>
</g>
</g>
<g id="gp_node2">
<rect x="0" y="100" width="1024" height="10" id="node2"></rect>
<g id="gm_node2">
<circle cx="200" cy="200" r="10" id="subnode2"></circle>
<text x="0" y="10" id="textsubnode2">subnode2</text>
</g>
</g>
</svg>
It worked (except the attributes) but I do not think, that it is the best way to do it, especially the update function (had to comment the return). The code I ended up with is:
var json = {"mainnodes":[{"name":"node1","y":50,"subnodes":[{"name":"subnode1","x":100}]},{"name":"node2","y":100,"subnodes":[{"name":"subnode2","x":200}]}]};
var json2 = {"mainnodes":[{"name":"node1","y":50,"subnodes":[{"name":"subnode1","x":100}]},{"name":"node2","y":150,"subnodes":[{"name":"subnode2","x":200}]}]};
var data = json;
var structure;
var svgContainer = d3.select("body")
.append("svg")
.attr("width", 1024)
.attr("height", 700);
function update(){
structure = svgContainer.selectAll("g")
.data(data.mainnodes)
.join(
function(enter) {
return enter
.append("g")
.attr("id",function(d){return "gp_"+d.name;})
.append("rect")
.attr("x",0)
.attr("y",function(d){return d.y;})
.attr("width",1024)
.attr("height",10)
.attr("id",function(d){return d.name;})
.each(function(d) {
var g = d3.select(this.parentNode)
.append("g")
.attr("id",function(d){return "gm_"+d.name;})
g.data(d.subnodes)
.append("circle")
.attr("cx",function(d){return d.x;})
.attr("cy",200)
.attr("r",10)
.attr("id",function(d){return d.name;});
g.data(d.subnodes)
.append("text")
.attr("x",0)
.attr("y",10)
.attr("id",function(d){return "text"+d.name;})
.text(function(d){return d.name;});
})
},
function(update) {
var s = d3.select("g");
s.attr("id",function(d){return "gp_"+d.name;});
s.select("rect")
.attr("x",0)
.attr("y",function(d){return d.y;})
.attr("width",1024)
.attr("height",10)
.attr("id",function(d){return d.name;});
var g = s.select("g");
g.attr("id",function(d){return "gm_"+d.name;});
g.select("circle")
.attr("cx",function(d){return d.x;})
.attr("cy",200)
.attr("r",10)
.attr("id",function(d){return d.name;});
g.select("text")
.attr("x",0)
.attr("y",10)
.attr("id",function(d){return "text"+d.name;})
.text(function(d){return d.name;});
//return update;
},
function(exit) {
return exit;
}
)
}
d3.select('svg').on('click', function(){
data = json2;
update();
})
update();
In all examples I saw so far the enter function had only one element appended (so update and exit is always is referring to this one element only). But if I split the append functions up into separate joins, I am not able to get the SVG structure I need. I already tried a lot of variations. Maybe someone can show me how to do it correctly. Thanks!
