如何无需d3.hierarchy或多层级,用D3.js实现纯数值数组树形图?
不用d3.hierarchy实现扁平数值数组的Treemap布局
当然可以不用d3.hierarchy来实现!你的数据是扁平的单层级数值数组,根本没必要动用专门处理层级数据的d3.hierarchy——d3.treemap只需要输入符合特定结构的节点对象,不一定非得由d3.hierarchy生成。下面给你两种简单的实现方式:
方法一:手动构造Treemap所需的节点结构
我们直接创建一个根节点对象,把数值数组转换成带value属性的子节点数组,再手动计算根节点的总数值(替代d3.hierarchy的sum方法),就能让d3.treemap正常工作:
const data = [32, 16, 37, 56]; const treeMapLayout = d3.treemap().size([400, 200]).paddingOuter(10); // 手动构造根节点:包含children数组,每个子节点存对应的数值 const root = { children: data.map(num => ({ value: num })) }; // 手动计算根节点的总value(对应d3.hierarchy的sum逻辑) root.value = root.children.reduce((total, child) => total + child.value, 0); // 应用treemap布局 treeMapLayout(root); // 绘制矩形(直接用根节点的children,不用descendants) d3.select('svg g') .selectAll('rect') .data(root.children) .enter() .append('rect') .attr('x', d => d.x0) .attr('y', d => d.y0) .attr('width', d => d.x1 - d.x0) .attr('height', d => d.y1 - d.y0)
对应的CSS和HTML和你原来的完全一致,不需要修改:
rect { fill: cadetblue; opacity: 0.3; stroke: white; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> <svg width="420" height="220"> <g></g> </svg>
方法二:核心逻辑简化说明
其实d3.treemap的核心要求非常简单,只要满足两个条件就能工作:
- 根节点有
value属性(存储所有子节点的数值总和) - 根节点有
children数组,每个子节点拥有自己的value属性
只要符合这个结构,不管节点是手动创建还是其他方式生成,d3.treemap都能正确计算出每个子节点的位置和尺寸。
补充:你原来代码的问题
你最初用d3.hierarchy(data)处理纯数值数组时,d3.hierarchy会把整个数组当成一个单节点,而root.sum(d => d.value)里的d是数组本身,并没有value属性,所以无法正确计算数值总和,自然也生成不了正确的treemap布局——手动构造节点结构反而能更准确地控制数据逻辑。
内容的提问来源于stack exchange,提问作者Sosa
相关产品推荐
相关产品推荐

