var svg = d3
.select("body")
.append("svg")
.attr("width", 600)
.attr("height", 600)
.append("g")
.attr("transform", "translate(50,50)");
//tree data
var data = [
{ child: "Alice", parents: [] },
{ child: "Bob", parents: [] },
{ child: "Carol", parents: [] },
{ child: "Dave", parents: ["Alice", "Bob"] },
{ child: "Eve", parents: ["Alice", "Bob"] },
{ child: "Francis", parents: ["Bob", "Carol"] },
{ child: "Graham", parents: ["Carol"] },
{ child: "Hugh", parents: ["Eve", "Graham"] },
];
// Process the nodes, add a pseudo root node so we don't have
// multiple roots
data.forEach(function(d) {
d.parentId = d.parents.length > 0 ? d.parents[0] : "root";
});
data.unshift({ child: "root", parentId: "" });
//to construct
var dataStructure = d3
.stratify()
.id(function (d) {
return d.child;
})
.parentId(function (d) {
return d.parentId;
})(data);
//to define the size of the structure tree
var treeStructure = d3.tree().size([500, 300]);
var root = treeStructure(dataStructure);
var nodes = root.descendants()
.filter(function(d) { return d.id !== "root"; });
// Custom way to get all links we need to draw
var links = [];
nodes.forEach(function(node) {
node.data.parents.forEach(function(parentId) {
var parentNode = nodes.find(function(d) { return d.id === parentId; });
links.push({
source: parentNode,
target: node,
});
});
});
//to make the connections curves
var connections = svg.append("g").selectAll("path").data(links);
connections
.enter()
.append("path")
.attr("d", function (d) {
return (
"M" +
d.source.x +
"," +
d.source.y +
" C " +
d.source.x +
"," +
(d.source.y + d.target.y) / 2 +
" " +
d.target.x +
"," +
(d.source.y + d.target.y) / 2 +
" " +
d.target.x +
"," +
d.target.y
);
});
//creating the circles with data info
var circles = svg
.append("g")
.selectAll("circle")
.data(nodes);
//placing the circles
circles
.enter()
.append("circle")
.attr("cx", function (d) {
return d.x;
})
.attr("cy", function (d) {
return d.y;
})
.attr("r", 7)
.append("text");
//names
var names = svg.append("g").selectAll("text").data(nodes);
names
.enter()
.append("text")
.text(function (d) {
return d.id;
})
.attr("x", function (d) {
return d.x + 7;
})
.attr("y", function (d) {
return d.y + 4;
});
circle {
fill: rgb(88, 147, 0);
}
path {
fill: none;
stroke: black;
}
<script src="https://d3js.org/d3.v6.min.js"></script>