ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

d3.partition 分区布局完全指南:用 d3-hierarchy 构建 Icicle 与 Sunburst 邻接图

d3.partition 分区布局完全指南:用 d3-hierarchy 构建 Icicle 与 Sunburst 邻接图 d3.partition 分区布局完全指南用 d3-hierarchy 构建 Icicle 与 Sunburst 邻接图【免费下载链接】d3Bring data to life with SVG, Canvas and HTML. :bar_chart::chart_with_upwards_trend::tada:项目地址: https://gitcode.com/GitHub_Trending/d3/d3本文围绕 d3 仓库中的 Partition 布局文档docs/d3-hierarchy/partition.md展开系统讲解 d3-hierarchy 提供的分区partition布局它如何把层级结构转换成充满空间的邻接图矩形 icicle 图或环形 sunburst 图、x0 / y0 / x1 / y1四个输出坐标的确切含义以及size、round、padding三个配置项的默认值与用法。读完本文你可以直接写出可运行的 icicle 图代码并理解布局计算的前提条件必须先sum、建议先sort与坐标输出设计背后的工程考量。什么是分区布局邻接图的思想分区布局partition layout生成的是邻接图adjacency diagram一种充满空间space-filling的 node-link 树图变体。与 node-link 图在父子节点之间画连线不同partition 布局把每个节点画成实心区域——矩形即 icicle 冰柱图或圆弧扇形即 sunburst 日环图节点之间的相对位置本身即表达了层级关系而区域的大小则编码了一个量化维度如收入、文件体积、占比。这个维度在 node-link 图中很难直观呈现。在 d3-hierarchy 模块总览中partition 被归类为三类层级可视化技术之一Node-link 图用离散标记节点 连线表达拓扑如 tree、cluster邻接图通过节点相对位置表达拓扑可同时用面积编码数量维度。icicle 图用矩形、sunburst 用环形扇区两者都由 partition 布局产生包含图通过包含关系表达拓扑如 treemap、pack。需要说明partition 布局的实现源码位于d3-hierarchy包对应版本为^3.1.2见 package.json 的 dependencies 与 yarn.lock 中的解析结果中的src/partition.js。当前仓库是 d3 元包与官方文档仓库src/index.js 只做export * from d3-hierarchy这样的再导出因此仓库内不包含partition.js本体本文对实现的描述以官方文档与 CHANGES.md 为准。API 一览方法与默认值Partition 的完整 API 只有五个成员全部见 api.md 中的索引。整理成表如下成员作用默认值partition()以默认设置创建一个新的 partition 布局—*partition*(*root*)对给定roothierarchy执行布局向root及其所有后代写入坐标属性—*partition*.size(*size*)设置布局尺寸为二元数组[width, height]不传参时返回当前尺寸[1, 1]*partition*.round(*round*)按布尔值开启/关闭坐标取整不传参时返回当前取整状态false*partition*.padding(*padding*)设置节点相邻子节点之间的间距数字不传参时返回当前 padding0所有方法都遵循 d3 一贯的 getter/setter 风格传参则设置并返回布局本身可链式调用不传参则返回当前值。partition(root) 的输出坐标布局计算会在root及其每个后代节点上写入四个属性node.x0— 矩形左边缘node.y0— 矩形顶边缘node.x1— 矩形右边缘node.y1— 矩形底边缘文档同时给出两条硬性前提必须先调用node.sum或node.count再传入布局。partition 依赖node.value决定每个节点占据的宽度未求和的节点没有value建议先调用node.sort排好序再计算布局。排序发生在布局之前才会影响子节点的排布顺序。这一点在 hierarchy.md 中有对应的推荐排序方式——对 icicle 图推荐先按高度降序、再按聚合值降序root .sum((d) d.value) .sort((a, b) b.height - a.height || b.value - a.value);坐标输出为什么是 x0/x1 而不是 x0/dxCHANGES.md 记录了这一设计的历史v4.0.0 起d3.treemap与d3.partition两个空间填充布局改为输出x0, x1, y0, y1四个边缘坐标替代旧版的x0, dx, y0, dy宽度/高度形式。原因是精度相邻单元格的公共边缘在起点 宽度模式下可能因浮点运算出现微小偏差例如a.x0 a.dx与b.x0相差一个 ε而直接存边缘坐标可以保证相邻单元格边缘严格相等。同一版本中还为 partition 新增了round取整与padding间距支持。完整示例构建一张 icicle 图下面是一份可直接运行的完整流程数据 → stratify → hierarchy → sum/sort → partition → 渲染 SVG 矩形。数据沿用 stratify.md 文档中的表格结构name,parent两列 CSV因为多数真实业务数据组织、目录、科目都是这种扁平父子表而非嵌套 JSON。svg width960 height500/svg script srchttps://cdn.jsdelivr.net/npm/d37/script script const name Eve,Cain,Seth,Enos,Noam,Abel,Awan,Enoch,Azura; const parent ,Eve,Eve,Seth,Seth,Eve,Eve,Awan,Eve; const value 0,3,7,4,3,1,5,2,2; // 叶子节点带数值 // 1. 把扁平行转成层级stratify const table d3.csvParse(name \n parent \n value, (d) ({name: d.name, parent: d.parent, value: d.value})); const root d3.stratify() .id((d) d.name) .parentId((d) d.parent) (table); // 2. 求和 排序partition 的前置条件 root.sum((d) d.value) .sort((a, b) b.height - a.height || b.value - a.value); // 3. 布局显式指定画布尺寸 const width 960, height 500; d3.partition() .size([width, height]) .padding(2) // 相邻兄弟节点之间留 2px 缝隙 (root); // 4. 渲染x0/y0/x1/y1 直接映射为 rect 属性 d3.select(svg) .selectAll(rect) .data(root.descendants()) .join(rect) .attr(x, (d) d.x0) .attr(y, (d) d.y0) .attr(width, (d) Math.max(0, d.x1 - d.x0)) .attr(height, (d) Math.max(0, d.y1 - d.y0)) .attr(fill, (d) d3.schemeCategory10[d.depth % 10]); /script几个值得注意的细节size的默认值是[1, 1]即不设置时坐标落在[0,1]×[0,1]归一化区间内这对配合d3.scaleLinear二次映射很方便但直接画 SVG 必须显式设置画布尺寸padding(2)让相邻兄弟节点之间留出 2 像素的视觉分隔padding 越大缝隙越明显但会等比压缩节点可用面积渲染时d.x1 - d.x0可能出现极小的负值padding 作用于极小节点时用Math.max(0, ...)兜底是常见做法node.x0等四个属性是布局原地写入节点对象的布局函数本身不返回新的数据副本所以root.descendants()里每个节点都自带坐标。变体sunburst 日环图Icicle 与 sunburst 共用同一个布局只是渲染几何不同把y0/y1解释为半径、x0/x1解释为角度乘以 2π再交给 d3-shape 的 arc 生成器即可// 布局不变 d3.partition().size([2 * Math.PI, radius]) .padding(0.5) (root.sum((d) d.value)); // 渲染角度取弧度半径取 y0/y1 const arc d3.arc() .innerRadius((d) d.y0) .outerRadius((d) d.y1) .startAngle((d) d.x0) .endAngle((d) d.x1); svg.selectAll(path) .data(root.descendants()) .join(path) .attr(d, arc) .attr(fill, (d) d3.schemeCategory10[d.depth % 10]);从源码结构看arc 生成器以原点为中心、默认读取innerRadius / outerRadius / startAngle / endAngle字段见 arc.md因此只要把 partition 的坐标映射过去就能复用饼图/环图的圆角cornerRadius与角间隙padAngle能力配合d3.zoom还可以实现点击某个扇区后放大下钻的经典交互。使用与安装partition 属于 d3 主包的一部分。通过包管理器安装需要 Node12见 package.json 的 engines 声明npm install d3安装后既可以按 ESM 方式从主包整体导入src/index.js 会再导出d3-hierarchy的全部 API也可以单独安装d3-hierarchy当前锁定版本为 3.1.2见 yarn.lock。在浏览器环境中package.json 的exports字段声明了umd条件指向dist/d3.min.js即引入 UMD 构建后可直接使用全局d3.partition。在 d3 v7 中d3.partition、partition.size、partition.round、partition.padding的官方文档位置为 docs/d3-hierarchy/partition.mdAPI 索引位于 docs/api.md。常见坑与参数速查忘记sum导致节点消失未求和的节点value为undefined宽度为零矩形不可见。布局前必须root.sum((d) d.value)或root.count()。value必须非负node.sum 要求value访问器返回非负数字。若只想按叶子计数用root.sum((d) d.value ? 1 : 0)或对内部节点返回 0。size忘了设图形挤在左上角一像素默认[1, 1]是归一化坐标务必设置为目标画布的[width, height]sunburst 场景则为[2 * Math.PI, radius]。round的取舍开启取整后坐标为整数、SVG 渲染更锐利但大 padding 下可能出现相邻节点间出现 1px 错位默认关闭。排序时机node.sort必须在布局调用之前完成之后重排不会触发重排布——需要先sort再重新执行partition(root)。与 treemap 的区别treemap 是递归二分面积每个父节点区域内独立排布子节点支持多种切片算法与嵌套 paddingpartition 则是每层占据一条水平带深度越深越靠下因此 icicle 图能清晰展示每一层级的整体占比对比。小结Partition 布局是 d3-hierarchy 中 API 面最窄的布局之一——一个构造函数、一个可调用入口、三个配置方法——但它输出的x0/y0/x1/y1四个坐标足以驱动 icicle 与 sunburst 两种经典的面积编码层级图。使用它的关键链路只有三步stratify/hierarchy建树sumsort准备数据partition().size([...]).padding(n)(root)计算坐标。理解了边缘坐标代替宽度这一 v4 起的设计、以及默认size [1,1]的归一化行为就能避免绝大多数渲染问题。【免费下载链接】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),仅供参考
返回列表