当一份数据既有"目录"又有"文件",既要看每一份的体量、又要看它们如何归堆,矩形树图把两个问题压进同一张画布:矩形的面积严格正比于数值,矩形的包含关系复刻层级的包含关系。本页以一个开源前端组件库的代码量构成为标本,拆解这套编码的读法、边界与后备。
壹 / 主标本
贰 / 读图原理
面积 = 值 / 而不是长度或颜色
比较两个矩形时, 眼睛评估的是"占多大一块", 也就是面积。3,800 行的 DataTable.tsx 之所以比 2,400 行的 Button.tsx 大, 大的正好是那 1.58 倍的面积份额。
左块面积是右块的两倍, 对应 2 比 1 的数值。树图中所有比较最终都落回这一步。
嵌套 = 层级 / 包含关系可视化
文件矩形画在目录矩形内部, 因为文件本来就属于目录。squarified 布局算法在父矩形内部递归切分, 让每个子矩形尽量接近正方形, 小数点级的面积比例由切分宽度精确保证。
本图两层: 仓到目录、目录到文件。第三层起可读性开始崩塌, 见下方警示。
色相 = 归属 / 面积之外的第二通道
目录之间用互异色相, 目录之内用同一色相的深浅档, 颜色回答"它属于谁", 不承担数值编码。数值只由面积负责, 白色分隔边负责让相邻色块不粘连。
代码库中对应 src/components 与 tests 一眼可分, 而 DataTable.tsx 与 Select.tsx 的深浅差异只表示同族内的排序档位。
叁 / 深度警示
把上图的 33 个文件再向下拆到"导出函数"甚至"语句块", 节点数会冲破 300。此时每个矩形的边长不足 10 像素: 名称写不下、焦点框挤不进、 Hover 目标小于指尖。层级深度大于 3 层时不应使用树图, 这是选型数据中的硬边界。
肆 / 同数据异形
把主图压回单层(只看 8 个目录), 再用旭日图重画同一份目录值。左图拼的是面积, 右图拼的是角度与半径。
伍 / 数据表后备
树图依赖面积估读与色彩分组, 对屏幕阅读器与低视力用户风险等级为 high。因此完整数据以表格为主视图静态呈现, 不依赖脚本; 悬停表格行会在上方树图中高亮对应矩形。
| 路径 | 行数 | 占目录 | 占全仓 | 文件角色 |
|---|---|---|---|---|
| src/components / 21,600 行 / 36.9% | ||||
| src/components/DataTable.tsx | 3,800 | 17.6% | 6.5% | 组件源码 |
| src/components/DatePicker.tsx | 3,400 | 15.7% | 5.8% | 组件源码 |
| src/components/Select.tsx | 2,900 | 13.4% | 4.9% | 组件源码 |
| src/components/Tree.tsx | 2,600 | 12.0% | 4.4% | 组件源码 |
| src/components/Button.tsx | 2,400 | 11.1% | 4.1% | 组件源码 |
| src/components/Form.tsx | 2,200 | 10.2% | 3.8% | 组件源码 |
| src/components/Modal.tsx | 2,100 | 9.7% | 3.6% | 组件源码 |
| src/components/Input.tsx | 2,000 | 9.3% | 3.4% | 组件源码 |
| src/components/index.ts | 200 | 0.9% | 0.3% | 导出入口 |
| src/core / 9,800 行 / 16.7% | ||||
| src/core/renderer.ts | 4,100 | 41.8% | 7.0% | 内核 |
| src/core/state.ts | 2,900 | 29.6% | 4.9% | 内核 |
| src/core/scheduler.ts | 1,800 | 18.4% | 3.1% | 内核 |
| src/core/types.ts | 1,000 | 10.2% | 1.7% | 类型定义 |
| tests / 7,300 行 / 12.5% | ||||
| tests/components.test.tsx | 3,600 | 49.3% | 6.1% | 测试 |
| tests/core.test.ts | 2,200 | 30.1% | 3.8% | 测试 |
| tests/hooks.test.ts | 1,500 | 20.5% | 2.6% | 测试 |
| src/hooks / 5,400 行 / 9.2% | ||||
| src/hooks/useVirtualList.ts | 2,400 | 44.4% | 4.1% | 组合函数 |
| src/hooks/useFormControl.ts | 1,300 | 24.1% | 2.2% | 组合函数 |
| src/hooks/useDragSort.ts | 1,100 | 20.4% | 1.9% | 组合函数 |
| src/hooks/useMediaQuery.ts | 600 | 11.1% | 1.0% | 组合函数 |
| src/utils / 4,900 行 / 8.4% | ||||
| src/utils/dom.ts | 2,200 | 44.9% | 3.8% | 工具函数 |
| src/utils/date.ts | 1,500 | 30.6% | 2.6% | 工具函数 |
| src/utils/format.ts | 800 | 16.3% | 1.4% | 工具函数 |
| src/utils/debounce.ts | 400 | 8.2% | 0.7% | 工具函数 |
| docs / 4,600 行 / 7.8% | ||||
| docs/api-reference.md | 1,800 | 39.1% | 3.1% | 文档 |
| docs/getting-started.md | 1,400 | 30.4% | 2.4% | 文档 |
| docs/theming.md | 800 | 17.4% | 1.4% | 文档 |
| docs/migration.md | 600 | 13.0% | 1.0% | 文档 |
| src/styles / 3,500 行 / 6.0% | ||||
| src/styles/tokens.css | 1,900 | 54.3% | 3.2% | 样式 |
| src/styles/reset.css | 900 | 25.7% | 1.5% | 样式 |
| src/styles/animations.css | 700 | 20.0% | 1.2% | 样式 |
| scripts / 1,500 行 / 2.6% | ||||
| scripts/build.js | 900 | 60.0% | 1.5% | 构建脚本 |
| scripts/release.js | 600 | 40.0% | 1.0% | 发布脚本 |
| 总计 / 8 个目录 / 33 个文件 | 58,600 | 100% | 100% | 全仓 |
键盘路径: Tab 逐个聚焦树图矩形与目录条 / Enter 或 Space 折叠展开目录 / Backspace 展开全部回到总览 / 聚焦时读数条与提示框同步报出名称、行数与占比。