d3.treemap()仅计算坐标不绘图,需配合渲染;关键步骤:d3.hierarchy()构建层级、treemap.size().padding()配置布局、layout(root)生成x0/y0/x1/y1;数据须含value字段或用sum()指定,父节点value需显式累加;推荐按depth或value着色,响应式应复用layout实例而非重建。

用 d3.js 的 d3.treemap() 生成基础矩形树图
原生 HTML 没有矩形树图(Treemap)标签,必须依赖 JavaScript 可视化库。当前最稳定、文档最全、适配性最强的是 d3.js v6+ 的 d3.treemap() ——它不画图,只计算每个节点的 x0、y0、x1、y1 坐标,你用 <rect></rect> 渲染即可。
关键步骤:
- 先用
d3.hierarchy()把嵌套数据转成层级结构,注意children字段名要匹配(默认找children,若字段是subs需传入访问器:d3.hierarchy(root, d => d.subs)) - 调用
d3.treemap().size([width, height]).padding(1)构建布局器,padding控制矩形间距,设为 0 会贴边但难区分相邻块 - 执行
layout(root)后,每个节点会多出x0/y0/x1/y1四个数值属性,直接绑定到<rect></rect>的x、y、width、height
数据中必须带 value 字段,否则所有块面积为 0
d3.treemap() 默认按节点的 value 属性分配面积。如果数据里没这个字段,或字段名不一致(比如叫 size 或 count),渲染出来全是等宽高小方块,甚至报错 NaN 宽高。
解决方法:
立即学习“前端免费学习笔记(深入)”;
将 Markdown 文章转换为微信公众号兼容的纯 HTML 格式。当用户要求"转成微信格式"、"生成公众号文章 HTML"、"排版到微信草稿箱"、"微信粘贴格式"时触发。输出带内联样式的纯 HTML,微信编辑器可直接渲染,无需额外适配。支持标题、段落、列表、粗体、行内代码、表格、引用块、代码块、配图的完整转换。
- 预处理数据:遍历节点,补上
value(叶子节点通常填数值,父节点可设为子节点value之和) - 或用
sum方法自定义取值逻辑:layout.sum(d => d.size || d.count || 0) - 特别注意:父节点的
value不会自动累加,必须显式计算好再传入,否则 treemap 会把父节点当叶子处理,导致层级错乱
颜色映射别直接用 name,优先按深度或 value 分级
常见错误是给每个 <rect></rect> 填 fill="#xxx" 写死,或用节点 name 做哈希色 —— 这会导致同名不同层的块颜色重复,且无法反映数据量级差异。
更实用的做法:
- 按深度着色:
d3.scaleOrdinal(d3.schemeCategory10).domain([0, 1, 2]),然后fill(scale(node.depth)) - 按
value线性渐变:d3.scaleLinear().domain([minVal, maxVal]).range(['#eee', '#222']) - 鼠标悬停时用
title显示完整name和value,比塞在矩形里更清晰
响应式重绘时别反复调用 d3.treemap(),缓存 layout 实例
窗口缩放时若每次重新调用 d3.treemap().size([...]),会重建整个布局函数,性能差且可能触发重复绑定事件。正确做法是复用同一个 layout 实例,只更新尺寸:
const treemap = d3.treemap().padding(1); // 初始渲染 treemap.size([width, height])(root); // resize 时 treemap.size([newWidth, newHeight])(root); // 直接重算坐标,不新建对象
另外,<svg></svg> 宽高建议用 JS 动态设置 attr('width')/attr('height'),避免 CSS 缩放导致像素模糊。
真正麻烦的是数据更新后如何平滑过渡 —— d3.treemap() 本身不支持动画,得靠 selection.transition().attrTween() 手动插值 x0→x1 等四个坐标,稍不注意就卡顿。除非强需求,否则首次实现建议先关掉过渡。


















