I\'m trying to show the relationship between SQL tables in visualization. I have three columns in a csv sheet (columns: Target, Source, JoinSource).
Column Targe
Note: your original sample data had missing nodes in the tree hierarchy, which I've filled in manually.
I've transformed the data into the form {id, parentId, name}
where P3.1.1 will emit {id: "P3.1.1", parentId: "P3.1", name: "Earth"}
. This can be fed to d3.stratify
that will build the hierarchy for you. I also a {id: "P", name: "Target"}
for the root node.
d3-stratify:
https://github.com/d3/d3-hierarchy/blob/master/README.md#stratify
demo
I used this demo for hierarchy with a few adjustments to build the SVG tree: d3-hierarchy (demo)
label
was changed to extract name
property by default instead of id
, and I've embedded the dimensions directly into the function.
It uses d3 Tidy Tree (demo) to render a d3-hierarchy.
data = `[P1 Apple, P2 Mango, P2.1 Pluto, P3.1.1 Earth, P10 Red, P10.1 Blue, P10.1.1 Copper, P3 PewPewPew, P3.1 Chopper, P3.2 Twenty, P3.1.2 Two]`
.slice(1,-1).split(', ')
.map(x=>x.match(/^((.*?)(?:\.)?(?:\d*)?) (.*)$/).slice(1))
.map(([id, parentId, name])=>({id, parentId, name}))
data.push({id: 'P', name:'Target'})
document.body.appendChild(graph(d3.stratify()(data)))
function graph(root, {
label = d => d.data.name,
highlight = () => false,
marginLeft = 40
} = {}) {
width=500;
dx=12;
dy=120;
treeLink = d3.linkHorizontal().x(d => d.y).y(d => d.x);
tree = d3.tree().nodeSize([dx, dy]);
root = tree(root);
let x0 = Infinity;
let x1 = -x0;
root.each(d => {
if (d.x > x1) x1 = d.x;
if (d.x < x0) x0 = d.x;
});
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, x1 - x0 + dx * 2])
.style("overflow", "visible");
const g = svg.append("g")
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.attr("transform", `translate(${marginLeft},${dx - x0})`);
const link = g.append("g")
.attr("fill", "none")
.attr("stroke", "#555")
.attr("stroke-opacity", 0.4)
.attr("stroke-width", 1.5)
.selectAll("path")
.data(root.links())
.join("path")
.attr("stroke", d => highlight(d.source) && highlight(d.target) ? "red" : null)
.attr("stroke-opacity", d => highlight(d.source) && highlight(d.target) ? 1 : null)
.attr("d", treeLink);
const node = g.append("g")
.attr("stroke-linejoin", "round")
.attr("stroke-width", 3)
.selectAll("g")
.data(root.descendants())
.join("g")
.attr("transform", d => `translate(${d.y},${d.x})`);
node.append("circle")
.attr("fill", d => highlight(d) ? "red" : d.children ? "#555" : "#999")
.attr("r", 2.5);
node.append("text")
.attr("fill", d => highlight(d) ? "red" : null)
.attr("dy", "0.31em")
.attr("x", d => d.children ? -6 : 6)
.attr("text-anchor", d => d.children ? "end" : "start")
.text(label)
.clone(true).lower()
.attr("stroke", "white");
return svg.node();
}