我正在尝试创建一个描述预算数据的树状图。
预期:树状图内不应有任何空白;描绘每个节点的所有矩形都应该像乐高积木一样适合SVG内部。
实际:我的树形图的矩形在SVG中排列不正确;见下图:
目前,我的数据集还很浅,并且大部分是我所组成的虚拟数据。CSV文件的结构为:
这些是代码中的相关步骤:
步骤1:加载CSV文件后,我使用将该文件转换为层次结构d3.stratify()
:
`let dataStratified = d3
.stratify()
.id(function (d) {
return d.Child;
})
.parentId(function (d) {
return d.Parent;
})(results);`
第2步:然后我转到了分层布局d3.treemap()
:
let myTreemap = (data) =>
d3.treemap().size([width, height]).padding(1).round(true)(
d3
.hierarchy(data)
.sum((d) => d.data["Rs,millions"])
.sort((a, b) => b.data["Rs,millions"] - a.data["Rs,millions"])
);
const root = myTreemap(dataStratified);
Step 3: Using this Observable notebook as a guide, I proceeded to build the leaves of the treemap:
const leaf = g
.selectAll("g.leaf")
// root.leaves() returns all of the leaf nodes
.data(root.leaves())
.enter()
.append("g")
.attr("class", "leaf")
// position each group at the top left corner of the rect
.attr("transform", (d) => `translate(${d.x0},${d.y0})`)
.style("font-size", 10);
Step 4: And appended it to the SVG I had created:
// Now we append the rects.
leaf
.append("rect")
.attr("id", (d) => d.data.id)
.attr("fill", (d) => {
while (d.depth > 1) d = d.parent;
return color(d.data.data.Child);
})
.attr("opacity", 0.7)
// the width is the right edge position - the left edge position
.attr("width", (d) => d.x1 - d.x0)
// same for height, but bottom - top
.attr("height", (d) => d.y1 - d.y0)
// make corners rounded
.attr("rx", 3)
.attr("ry", 3);
The rest of the code is mostly styling and label placement so I don't think it's relevant to my question here but it can be viewed here: Github or CodeSandbox.
The mis-sized rects are due the total value of the treemap, you are essentially adding up the totals again on the parent node (because it is in the CSV column).
You should only sum if it is the leaf node (meaning if the obj has no children). In short, if you check for children in the hierarchy.sum
function, and only sum if there is no children, then it should calculate up the totals correctly
let dataHierarchy = d3
.hierarchy(dataStratified)
.sum(d => (d.children ? 0 : d.data["Rs,millions"]))
.sort((a, b) => b.data["Rs,millions"] - a.data["Rs,millions"]);
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句