如何用 d3.treemap 把层级数据渲染为矩形布局?

发布时间:2026/11/5 16:32:48

如何用 d3.treemap 把层级数据渲染为矩形布局? 如何用 d3.treemap 把层级数据渲染为矩形布局【免费下载链接】d3Bring data to life with SVG, Canvas and HTML. :bar_chart::chart_with_upwards_trend::tada:项目地址: https://gitcode.com/GitHub_Trending/d3/d3如果你手里有一份带数值的层级数据比如按目录统计的文件大小、按部门拆分的营收想把它画成一块被递归细分的矩形区域——即 treemap——那么 d3-hierarchy 的d3.treemap()就是布局计算工具。本文的完整目标是在浏览器里加载 D3从一份层级 JSON 出发调用d3.treemap()为每个节点算出x0, y0, x1, y1四个矩形坐标再把它们渲染成 SVG 矩形并验证结果。依据是仓库中的 d3-hierarchy/treemap 与 d3-hierarchy/hierarchy 文档。D3 在任何 JavaScript 环境都能运行。按 getting started 的说明官方推荐使用 CDN 托管的 ES module 包如果你需要不依赖模块加载的环境还有 UMD 包和 npm 安装两种替代方式。准备加载 D3 并确认数据形态treemap 文档要求布局的输入是一个 hierarchy 根节点因此数据必须满足两点数据本身是层级结构。文档给出的标准形态是一个根对象其children数组逐层嵌套子节点const data { name: Eve, children: [ {name: Cain}, {name: Seth, children: [{name: Enos}, {name: Noam}]}, {name: Abel}, {name: Awan, children: [{name: Enoch}]}, {name: Azura} ] };如果你的数据还是 CSV 等表格形式hierarchy 文档指出需要先用 stratify 整理成层级后再传给d3.hierarchy。每个参与面积计算的节点要有非负数值。node.sum的文档明确要求 value 访问函数返回非负数。下面把上面的示例数据补充value字段叶子节点取数值内部节点不取值后面代码即按这份数据编写const data { name: Eve, children: [ {name: Cain, value: 45}, {name: Seth, children: [{name: Enos, value: 10}, {name: Noam, value: 20}]}, {name: Abel, value: 30}, {name: Awan, children: [{name: Enoch, value: 15}]}, {name: Azura, value: 40} ] };加载 D3 有三种方式任选其一后文代码对三者通用CDN ES module文档推荐!DOCTYPE html div idcontainer/div script typemodule import * as d3 from https://cdn.jsdelivr.net/npm/d37/esm; // ……后文的完整代码…… container.append(svg.node()); /scriptCDN UMD用script srchttps://cdn.jsdelivr.net/npm/d37/script加载它导出全局d3后续代码不变。npm执行npm install d3文档也列出 yarn / pnpm 对应命令然后在模块里import * as d3 from d3;。此外 getting started 还提到 Observable 笔记本内置 D3、返回单元格生成的 DOM 元素即可展示图表可作为在线调试环境。第一步构建层级并计算节点数值用d3.hierarchy(data)从上面的data构造根节点const root d3.hierarchy(data);不指定 children 访问函数时默认取d.children正好匹配上面的数据结构。构造完成后每个节点带有node.data、node.depth、node.height、node.parent、node.children等属性其中node.value是需要你显式计算汇总的可选属性。treemap 文档写明必须在把层级交给 treemap 布局之前调用root.sum或root.count否则节点没有value可用。sum按后序遍历把每个节点的值设为自身访问函数返回值 所有子节点值之和访问函数收到的是节点的 dataroot.sum((d) d.value ?? 0);?? 0只用于本示例内部节点没有value字段返回 0 表示数值全部来自叶子。这正是文档给出的做法——如果你只想让叶子节点贡献数值对任何有 children 的节点返回 0例如root.sum((d) d.value ? 1 : 0)。若数据每个节点都自带汇总值则写成root.sum((d) d.value)。如果只想按叶子数量布局可以直接用root.count()它把每个节点值设为其下属叶子数。第二步配置并调用 treemap 布局treemap 文档 的默认值size默认为[1, 1]padding默认为 0round默认false平铺方法默认为黄金比例的treemapSquarify。因此要得到实际尺寸的布局必须先设置size。hierarchy文档给出的官方示例写法是// Construct the treemap layout. const treemap d3.treemap(); treemap.size([width, height]); treemap.padding(2);其中width和height是画布尺寸取你自己的值padding(2)同时设置内边距和外边距本文取 2 像素数值可自定。文档同时建议在计算布局前调用root.sort对层级排序treemap 推荐的比较方式是高度降序、值降序root.sort((a, b) b.height - a.height || b.value - a.value);注意 sort 的比较函数收到的是两个节点而不是两个 data这与Array.prototype.sort比较 data 的习惯不同。排序必须在调用布局前完成否则不影响本次布局结果。最后调用布局计算treemap(root);调用后root及其每个后代节点都被写入了四个属性这就是渲染的全部输入node.x0—— 矩形左边缘node.y0—— 矩形上边缘node.x1—— 矩形右边缘node.y1—— 矩形下边缘第三步把节点渲染成 SVG 矩形布局只负责坐标画矩形需要 d3-selection 的数据绑定。按 joining 文档 的selectAll().join()模式先创建 SVG 容器getting-started 的空白图表示例即d3.create(svg)再为每个后代节点生成一个rect// 创建 SVG 容器尺寸与上一步 size 一致 const svg d3.create(svg) .attr(width, width) .attr(height, height); // 为每个节点生成一个矩形 svg.append(g) .selectAll(rect) .data(root.descendants()) .join(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); // 展示在独立 HTML 页面里把 SVG 挂到容器上 container.append(svg.node());root.descendants()按拓扑序返回根节点 所有后代每个节点恰好对应一个rectjoin(rect)完成数据到元素的绑定。在 Observable 里则不需要container.append直接把svg.node()从单元格返回即可。验证布局结果文档没有给出成功日志但给出了可判断的坐标契约每个节点必须有x0, y0, x1, y1矩形宽高即x1 - x0与y1 - y0。运行后在浏览器控制台检查console.log(root.x0, root.y0, root.x1, root.y1); // 根节点四个坐标 const leaf root.leaves()[0]; console.log(leaf.data.name, leaf.x0, leaf.y0, leaf.x1, leaf.y1);可核对的点根节点与每个叶子的x1 x0且y1 y0宽高为正画出的矩形不翻转、不为零宽leaf.data.name应等于你在data里写的名字如示例中的 Cain说明node.data关联正确视觉上所有矩形铺满width × height区域相邻子块之间有 2 像素缝隙对应padding(2)没有任何矩形越出 SVG 边界。若某个区域缺失或错位先检查两处最常见的文档明确要求是否漏了root.sum(...)treemap 文档将其列为布局前的强制步骤以及size([width, height])是否设置成了你实际的画布尺寸而不是默认[1, 1]。调整平铺方式与可选配置treemap.tile 用于更换递归细分算法。默认的treemapSquarify实现 Bruls 等人的 squarified 算法目标矩形宽高比默认为黄金比例 φ (1 √5) / 2。文档说明该比例只是给算法的提示不保证每个矩形恰好等于该比例squarify.ratio(ratio)可以改目标比例要求 ≥ 1。其余内置方法的行为方法文档描述的行为treemapDice按子节点数值水平划分从左边缘x0起依次排布treemapSlice按子节点数值垂直划分从上边缘y0起依次排布treemapSliceDice奇数深度委托给 slice否则委托给 dice即按深度交替横竖切分treemapBinary递归划分成近似平衡的二叉树宽矩形用水平划分、高矩形用垂直划分treemapResquarify与 squarify 类似但保留上一次treemapResquarify布局中节点相邻关系适合做 treemap 的形变动画只改尺寸不改相对位置代价是后续布局不再是严格 squarify 结果切换方式const treemap d3.treemap() .tile(d3.treemapSliceDice) .size([width, height]) .padding(2);其余可选配置均为 treemap 文档给出的默认值round(true)开启坐标取整默认falsepaddingInner(n)/paddingOuter(n)分别单独控制内边距分隔相邻子节点与外边距分隔节点边缘与其子节点都默认 0也可传按节点取值的函数。完整示例与文档限制把上面各步拼起来是一个可整页运行的独立 HTMLESM CDN 加载其余按你的数据替换!DOCTYPE html div idcontainer/div script typemodule import * as d3 from https://cdn.jsdelivr.net/npm/d37/esm; const width 640; const height 400; const data { name: Eve, children: [ {name: Cain, value: 45}, {name: Seth, children: [{name: Enos, value: 10}, {name: Noam, value: 20}]}, {name: Abel, value: 30}, {name: Awan, children: [{name: Enoch, value: 15}]}, {name: Azura, value: 40} ] }; const root d3.hierarchy(data); const treemap d3.treemap() .size([width, height]) .padding(2); root.sum((d) d.value ?? 0); root.sort((a, b) b.height - a.height || b.value - a.value); treemap(root); const svg d3.create(svg) .attr(width, width) .attr(height, height); svg.append(g) .selectAll(rect) .data(root.descendants()) .join(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); container.append(svg.node()); /script运行后按上一节的验证清单检查。文档明确给出的边界只有两条布局前必须sum或count以及sum的访问函数必须返回非负数。若你的数据是表格而非层级先走 stratify若想让节点间留白更精细再阅读 treemap 文档 中paddingTop/Right/Bottom/Left的单独控制接口。【免费下载链接】d3Bring data to life with SVG, Canvas and HTML. :bar_chart::chart_with_upwards_trend::tada:项目地址: https://gitcode.com/GitHub_Trending/d3/d3创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/10/25 23:29:55

嵌入式AI与Python实战:从零构建课堂考勤系统毕业设计

简介:基于嵌入式AI技术的Python课堂考勤系统毕业设计资源,主要面向本科毕业生、课程设计学生及嵌入式AI应用开发者,围绕人脸识别课堂考勤场景,提供从硬件选型、电路设计、三维结构到软件算法与论文撰写的全流程参考。系统采用端侧…

2026/11/5 16:26:13

Rust原来很简单二:所有权系统

Part 2 核心篇 —— 所有权系统 本篇覆盖 第 6 ~ 10 章:所有权、借用与引用、生命周期、字符串与切片、内存模型。 ⚠️ 这是全书最重要的一篇。 把它吃透,Rust 从此“很简单”;跳过它,你会处处碰壁。请慢下来,动手敲每一段代码。 第 6 章 所有权:Rust 的第一性原理 6…

2026/11/5 15:00:49

基于Hadoop+Spark的民宿智能推荐系统设计与实现

1. 项目概述:大数据时代的民宿智能推荐这个毕业设计项目融合了当前大数据领域最主流的技术栈,构建了一个完整的民宿推荐系统解决方案。作为一名长期从事大数据系统开发的工程师,我认为这个选题非常贴合实际应用场景——随着旅游业的复苏和共享…

2026/11/5 14:10:30

ADS122U04IPWR+STM32F427ZI工业级温度测量信号链设计

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 14:10:30

UART接口24位ADC搭配RS485,解决远距离温度监控难题

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 14:10:30

UART接口24位ADC搭配PIC18F46K22的RTD与热电偶测温实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 13:55:19

GD32E10x官方例程入门:从GPIO点灯到串口调试

简介:这份GD32E10x系列官方例程面向嵌入式硬件与单片机开发者,基于ARM Cortex-M3内核,汇集兆易创新GD32E10x的示例代码,适合工业控制、消费电子、通信设备等场景的学习、验证与二次开发。压缩包共935个文件,约11.16MB&…

2026/11/5 15:39:06

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/5 0:02:07

多智能体协作系统架构设计与实践优化

1. 多智能体协作系统的时代背景2017年Transformer架构的诞生彻底改变了人工智能的发展轨迹。当行业还沉浸在单一大模型带来的性能突破时,Anthropic的研究团队已经将目光投向了更前沿的领域——如何让多个智能体通过协作产生超越单体能力的系统智能。这就像交响乐团中…

2026/11/5 0:02:07

大模型系统性入门实战指南:从原理到部署微调的全链路路线

提到大模型的系统性入门,我先说个结论:这事真不难,难的是资料太散、路线太多,今天这个框架明天那个工具,新人很容易在“收藏夹吃灰”和“教程看到一半放弃”之间反复横跳。市面上关于大模型的内容少说有几十万篇&#…

2026/11/5 0:02:07

鸿蒙文件系统沙箱机制解析与开发实践

1. 鸿蒙文件系统沙箱机制深度解析作为一名从Android转向鸿蒙开发的工程师,我深刻体会到文件系统访问是迁移过程中最先遇到的"拦路虎"。在Android上运行良好的文件读写代码,在鸿蒙真机环境却频频出现文件写入后神秘消失或直接抛出权限拒绝错误的…

2026/11/5 15:39:06

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/4 21:04:25

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑