G6 Fishbone Layout 实战指南:在 @antv/g6 中用鱼骨图布局呈现因果与层次数据 数据可视化前端图表库【免费下载链接】G6♾ A Graph Visualization Framework in JavaScript.项目地址https://gitcode.com/gh_mirrors/g6/G6点击查看免费下载Fishbone Layout鱼骨图布局是 antv/g6 内置的一种层次化图布局它通过模拟鱼骨形态把树形数据按层级排列成“鱼头 鱼脊 鱼肋”的结构特别适合因果分析、质量管理、故障归因等需要展示因果链与分类关系的场景。本文以 Fishbone.en.md 为主线结合 fishbone.ts 源码与 layout-fishbone.ts 测试用例带你掌握 Fishbone 布局的完整配置项、底层坐标计算原理与实战接入方式读完即可独立完成一张可交互的质量分析鱼骨图。Fishbone Layout 是什么Fishbone Layout 是 G6 内置的、专门用于表示层次结构数据的图形布局。它通过模拟鱼骨的形状将数据节点按照层次结构排列使数据的层次关系更加清晰直观。在 fishbone.ts 的类注释中官方将其对应到经典的 Ishikawa 图石川图又称因果图鱼头是问题或结果鱼脊是主干斜向伸出的“鱼肋”是各类原因分支。该布局特别适用于三类数据集层次结构数据如组织结构、分类体系问题分析过程如故障分析、质量分析典型如 QC 七大手法中的因果图决策过程如决策树、要素分析。由于它要求数据具备树形层次使用前通常需要将嵌套的树形数据转换为 G6 的图数据nodes edges。G6 提供了现成的转换工具treeToGraphData实现见 tree.ts它会深度优先遍历树为每个节点记录depth深度并把children转换为节点 id 数组与source/target边。快速上手最小可用配置Fishbone 是 G6 内置布局直接以type: fishbone声明即可无需额外注册import { Graph, treeToGraphData } from antv/g6; const graph new Graph({ layout: { type: fishbone, direction: LR, hGap: 50, vGap: 50, getRibSep: () 60, }, });一个完整的最小示例树形数据 折线边 画布拖拽import { Graph, treeToGraphData } from antv/g6; const graph new Graph({ layout: { type: fishbone, }, autoFit: view, data: treeToGraphData({ nodes: [ { id: root, data: { label: Root } }, { id: child1, data: { label: Child 1 } }, { id: child2, data: { label: Child 2 } }, { id: child3, data: { label: Child 3 } }, ], edges: [ { id: e1, source: root, target: child1 }, { id: e2, source: root, target: child2 }, { id: e3, source: root, target: child3 }, ], }), edge: { type: polyline, style: { lineWidth: 3, }, }, behaviors: [drag-canvas], });几点实战建议均有源码佐证官方示例普遍搭配edge.type: polyline。这是因为 Fishbone 布局会在布局结果中为每条边写入controlPoints见 fishbone.ts折线边利用这些控制点可绘出贴合“鱼脊 鱼肋”走向的路径建议开启autoFit: view树越深布局范围越大自动适配视口可以避免节点溢出交互上可叠加drag-canvas、zoom-canvas、drag-element参考 layout-fishbone.ts。配置项详解Fishbone 的完整配置项与默认值如下表来源Fishbone.en.md 与 FishboneLayoutOptions属性说明类型默认值必填type布局类型fishbone-✓direction布局方向RL从右到左鱼头在右、LR从左到右鱼头在左RL|LRRLhGap水平间距number节点最大宽度*vGap垂直间距number节点最大高度*getRibSep获取鱼肋间距的函数(node: NodeData) number() 60width布局宽度number画布宽度height布局高度number画布高度nodeSize节点尺寸number | [number, number] | [number, number, number] | ((node: NodeData) number | [number, number] | [number, number, number])-isLayoutInvisibleNodes不可见节点是否参与布局preLayout为 true 时生效boolean-nodeFilter参与该布局的节点筛选(node: NodeData) boolean-preLayout使用前布局在初始化元素前计算布局不适用于流水线布局boolean见下文说明*注表格中 hGap/vGap 官方文档未给出默认值但源码在execute()中做了兜底——当二者未配置时会用所有节点的最大宽度/高度作为默认间距见 fishbone.ts。direction鱼头朝向direction决定鱼头根节点的位置RL从右到左鱼头在右——这是源码static defaultOptions中的默认值fishbone.ts也是质量分析场景最常用的方向LR从左到右鱼头在左。从实现看RL并不是重新算一遍坐标而是在LR布局完成后执行一次水平镜像把每个节点的x变为width - x边的控制点同步镜像见rightToLeft方法fishbone.ts。因此width的取值会影响RL方向的最终坐标范围。hGap / vGap间距与斜率hGap控制相邻层级间的水平距离vGap控制同侧分支的垂直间距。源码中calculateX对奇数深度节点使用hGap / vGap作为斜率fishbone.ts因此二者的比值直接决定鱼肋的倾斜程度hGap相对越大鱼肋越平缓vGap相对越大鱼肋越陡峭。交互调试时参考 fishbone.md官方示例将二者放在 20100 区间内步进 10 调整。getRibSep鱼肋间距getRibSep是一个以节点为入参的函数返回该节点所在鱼肋一级分支与其相邻鱼肋之间的间距默认() 60。在doLayout中ribX鱼脊上各肋的锚点 X 坐标由getSize(root)[0] getRibSep(root)起步fishbone.ts并且每处理一个深度为 1 的节点都会用x getRibSep(node)更新临时肋间距fishbone.ts。这意味着你可以按节点返回不同的值实现“大分支更宽、小分支更窄”的自适应鱼骨。nodeSize节点尺寸既可以是数值/数组也可以是一个返回尺寸的函数最终经parseSize规范化为标准尺寸参与间距计算formatSize方法fishbone.ts。当节点使用不同大小如按权重缩放时通过函数形式返回可以让布局间距与实际渲染尺寸保持一致。preLayout 与 isLayoutInvisibleNodespreLayout表示在初始化元素之前先计算布局。G6 在inferLayoutOptions中会自动为fishbone等布局打开preLayout: true见 runtime/options.ts其中 L35 将fishbone列入清单。因此你通常无需手动配置它文档同时提示该选项“不适用于流水线布局”当你使用流水线式布局编排时需注意这一限制。isLayoutInvisibleNodes则控制在preLayout: true时不可见节点是否参与布局计算用于控制visibility相关场景的布局稳定性。nodeFilternodeFilter继承自BaseLayoutOptionslayouts/types.ts用于筛选哪些节点参与本次布局便于在同一画布中做局部重排。源码级原理解析坐标是怎么算出来的深入 doLayout可以发现 Fishbone 布局的核心是一组基于树深度奇偶性的坐标推导单根约束getRoot()通过model.getRootsData()获取根节点当根节点数量为空或超过 2 个时直接返回fishbone.ts取第一个根作为鱼头。因此 Fishbone 面向的是单根树数据多根或不连通图不会生效。深度奇偶分流isAtEvenDepth判断节点深度是否为偶数fishbone.ts。偶数深度节点的 X 由“辅助点 水平偏移”推算奇数深度节点则沿鱼脊方向按hGap / vGap斜率推算两条路径共同保证了树形不会重叠。交替翻转placeAlterative会把索引为奇数的鱼肋index % 2 ! 0的一级分支连同其全部子孙绕鱼头 Y 轴做垂直镜像fishbone.ts。这就是鱼骨图“上下交错排布”的视觉效果来源——偶数肋在上、奇数肋在下视觉上呈鱼骨状。边控制点布局完成后每条入边都会获得一个控制点getAuxiliaryPoint(node), y或父节点 y并写入边的controlPointsfishbone.ts折线边据此画出符合鱼骨走向的连线。结果回写execute最终把节点坐标与边控制点通过assignElementStyle合并进元素样式后返回fishbone.ts。从架构上看Fishbone 与内置布局一样继承自抽象基类BaseLayoutbase-layout.ts并在 build-in.ts 中以fishbone: FishboneLayout注册进内置布局表同时从 layouts/index.ts 对外导出FishboneLayout与FishboneLayoutOptions类型。完整实战质量管理因果鱼骨图经典的质量分析场景是“人机料法环测”Man Power / Machine / Material / Method / Measurement / Milieu六大要素。下面这段代码来自 layout-fishbone.ts用树形数据构造了一张完整的多层鱼骨图并通过 GUI 面板动态切换directionimport { Graph, treeToGraphData } from antv/g6; const data { id: Quality, children: [ { id: Machine, children: [{ id: Mill }, { id: Mixer }, { id: Metal Lathe, children: [{ id: Milling }] }], }, { id: Method }, { id: Material, children: [ { id: Masonite, children: [ { id: spearMint }, { id: pepperMint, children: [{ id: test3 }] }, { id: test1, children: [{ id: test4 }] }, ], }, { id: Marscapone, children: [{ id: Malty }, { id: Minty }], }, { id: Meat, children: [{ id: Mutton }] }, ], }, { id: Man Power, children: [ { id: Manager }, { id: Masters Student }, { id: Magician }, { id: Miner }, { id: Magister, children: [{ id: Malpractice }] }, { id: Massage Artist, children: [{ id: Masseur }, { id: Masseuse }] }, ], }, { id: Measurement, children: [{ id: Malleability }] }, { id: Milieu, children: [{ id: Marine }] }, ], }; export const layoutFishbone async (context) { const graph new Graph({ ...context, container: container, autoFit: view, data: treeToGraphData(data), node: { type: rect, style: { size: [32, 32], label: false, labelFill: #262626, labelFontFamily: Gill Sans, labelMaxLines: 2, labelMaxWidth: 100%, labelPlacement: center, labelText: (d) d.id, labelWordWrap: true, }, }, edge: { type: polyline, style: { lineWidth: 3 }, }, layout: { type: fishbone, vGap: 48, hGap: 48, direction: RL, }, behaviors: [drag-canvas, zoom-canvas, drag-element], animation: false, }); await graph.render(); layoutFishbone.form (panel) { const config { type: fishbone, direction: RL }; return [ panel .add(config, direction, [LR, RL]) .name(Direction) .onChange((value) { graph.setLayout((prev) ({ ...prev, direction: value })); graph.render(); }), ]; }; return graph; }; layoutFishbone();这段代码的要点数据形态传入的是嵌套children的树treeToGraphData负责转换成图数据文档中还有一种等价写法直接给节点数据加depth字段、children存子节点 id 数组效果一致动态切换方向通过graph.setLayout((prev) ({ ...prev, direction: value }))局部更新布局配置再调用graph.render()重新布局。文档与 fishbone.md 均提示切换方向后部分节点可能溢出屏幕建议重新执行fitView或保持autoFit: view样式配合矩形节点 居中标签 折线边是鱼骨图最直观的呈现组合。小结Fishbone Layout 把经典的 Ishikawa 因果图带进了 G6direction控制鱼头朝向hGap/vGap决定鱼肋斜率getRibSep调节肋间距底层通过深度奇偶分流、奇数肋交替翻转与RL镜像三套机制生成鱼骨形态。配合treeToGraphData转换树数据、polyline折线边复用布局控制点你可以在几十行代码内构建出可用于质量管理、故障归因、决策分析的交互式鱼骨图。想进一步调整细节可参考交互式演示 fishbone.md 的 GUI 配置面板或直接在 layout-fishbone.ts 基础上改造数据与样式。赞分享数据可视化前端图表库【免费下载链接】G6♾ A Graph Visualization Framework in JavaScript.项目地址https://gitcode.com/gh_mirrors/g6/G6点击查看免费下载相关推荐G6 鱼骨图布局Fishbone Layout实战指南从配置参数到源码原理G6 鱼骨图布局Fishbone Layout实战指南从配置参数到源码原理 鱼骨图又称 Ishikawa 图、因果图是质量管理与因果分析中最经典的层次数据可视化前端图表库G6antv/g6基于 Changeset 的版本发布流程实战指南G6antv/g6基于 Changeset 的版本发布流程实战指南 导读 本文以 G6 仓库根目录的 PUBLISH.md https://link.gi数据可视化前端图表库G6 布局 API 完全指南setLayout / getLayout / layout / stopLayout 与组合布局实战G6 布局 API 完全指南setLayout / getLayout / layout / stopLayout 与组合布局实战 导读 本文围绕 G6An数据可视化前端图表库创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考