拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Mermaid ELK 布局引擎深度解析:@mermaid-js/layout-elk 的版本演进、配置参数与渲染管线

Mermaid ELK 布局引擎深度解析mermaid-js/layout-elk 的版本演进、配置参数与渲染管线【免费下载链接】mermaidGeneration of diagrams like flowcharts or sequence diagrams from text in a similar manner as markdown项目地址: https://gitcode.com/GitHub_Trending/me/mermaid本文基于仓库中 packages/mermaid-layout-elk/CHANGELOG.md 的完整版本记录系统梳理mermaid-js/layout-elk包的演进脉络0.1.1 → 0.2.3逐一拆解各版本引入的elk.*配置项mergeEdges、keepEntryNodeOnTop、nodePlacementAlignment等在源码中的真实接线方式并深入渲染管线ELK 图构建、跨子图边处理、边裁剪与圆角折线生成帮助你在项目或站点中正确接入并使用 Mermaid 的 ELK 布局引擎。一、包的定位与包元信息mermaid-js/layout-elk是为 Mermaid 提供的基于 Eclipse ELK通过elkjs的布局引擎插件包。它不是独立的图表库而是一个布局加载器Layout Loader主包mermaid保留原有的 Dagre 布局用户按需注册 ELK 加载器后即可用layout: elk配置或flowchart-elk语法切换布局。packages/mermaid-layout-elk/package.json 中的关键元信息字段值说明namemermaid-js/layout-elknpm 包名version0.2.3与 CHANGELOG 中最新版本一致moduledist/mermaid-layout-elk.core.mjsES Module 入口typesdist/layouts.d.ts类型声明入口dependenciesd3 ^7.9.0、elkjs ^0.9.3依赖 d3 曲线工具与 ELK 打包版内核peerDependenciesmermaid ^11.0.2要求主包 11.x对应 0.1.1 起包 READMEpackages/mermaid-layout-elk/README.md特别提示支持 mermaid 的宿主站点默认不会提供 ELK 布局需要自行安装该包才能启用layout: elk。支持的五种布局算法从 layouts.ts 的源码可直接确认注册表const algos [elk.stress, elk.force, elk.mrtree, elk.sporeOverlap]; const layouts: LayoutLoaderDefinition[] [ { name: elk, loader, algorithm: elk.layered, // elk 别名实际跑的是 layered 分层布局 }, ...algos.map((algo) ({ name: algo, loader, algorithm: algo })), ];即五个可选值elk默认等价elk.layered分层布局、elk.stress力导向/应力布局、elk.force、elk.mrtree多根树布局、elk.sporeOverlapSpore 重叠布局。注意elk.layered本身也作为算法名传递给 ELK别名与算法名在 render.ts 中通过preparedLayout.algorithm解析见下文管线部分。二、接入方式与三种启用写法2.1 启用 ELK 布局的三种写法按 README 记载任选其一即可让普通flowchart走 ELK写法 1切换图表类型前缀flowchart-elk TD A -- B A -- C写法 2frontmatter 配置layout: elk--- config: layout: elk --- flowchart TD A -- B A -- C写法 3frontmatter 指定具体算法如 stress--- config: layout: elk.stress --- flowchart TD A -- B A -- C2.2 与打包器集成npm install mermaid-js/layout-elkimport mermaid from mermaid; import elkLayouts from mermaid-js/layout-elk; mermaid.registerLayoutLoaders(elkLayouts);核心 API 是mermaid.registerLayoutLoaders(...)把上面layouts.ts导出的LayoutLoaderDefinition[]注册进主包之后解析器遇到layout: elk*配置或xxx-elk图表类型时才会按需loader函数动态import(./render.js)加载 ELK 渲染器。三、版本演进全记录CHANGELOG 逐版本解读CHANGELOG 采用 changesets 生成的 Patch/Minor 分组格式。下面按时间倒序完整继承每一条记录并结合源码说明其实际落点。3.1 0.2.3对应 mermaid 11.17.0——两项新增配置elk.keepEntryNodeOnTopfeat让递归流自环回流图的入口节点固定在顶层。elk.nodePlacementAlignmentfeat暴露 BK 分层对齐策略配置。这两项在 defaultConfig.ts 中都有默认值elk: { mergeEdges: false, // 见 3.2 nodePlacementStrategy: BRANDES_KOEPF, nodePlacementAlignment: NONE, // 0.2.3 新增项默认 NONE forceNodeModelOrder: false, considerModelOrder: NODES_AND_EDGES, keepEntryNodeOnTop: false, // 0.2.3 新增项默认关闭 },3.2 0.2.2对应 mermaid 11.16.0——mergeEdges 子图传播修复fix(elk): propagateelk.mergeEdgesconfig to subgraphs in ELK layout — previously edges defined inside a subgraph were not merged even whenelk.mergeEdges: truewas set.修复前即使全局设置elk.mergeEdges: true定义在子图内部的边也不会被合并多条同起同止的边会各自画线视觉冗余。修复后该配置正确下传。源码印证在 render.ts 的buildSubgraphLayoutOptions中——子图的 layoutOptions 显式读取了同一份elkConfigconst layoutOptions: Recordstring, unknown { spacing.baseValue: 30, nodeLabels.placement: [H_CENTER V_TOP, INSIDE], elk.layered.mergeEdges: elkConfig?.mergeEdges, // ← 传播到子图 nodePlacement.strategy: elkConfig?.nodePlacementStrategy, elk.layered.nodePlacement.bk.fixedAlignment: elkConfig?.nodePlacementAlignment ?? DEFAULT_NODE_PLACEMENT_ALIGNMENT, // ← 0.2.3 新增 };而根图在createRootElkGraphrender.ts中同样读取elk.layered.mergeEdges: data4Layout.config.elk?.mergeEdges,3.3 0.2.1对应 mermaid 11.13.0——ELK 边默认改为圆角折线fix: use rounded right-angle edges for ELK layout —— ELK 布局的边从继承全局basis默认曲线改为默认rounded直角段 圆角转折修复了 ELK 边弯曲而非直角路由的问题issue #7213。非 ELK 布局不受影响仍保留原basis默认。源码印证render.ts 在把 ELK 返回的边段写回LayoutData时硬编码layoutEdge.curve rounded;3.4 0.2.0对应 mermaid 11.11.0Minorfeat: Update mindmap rendering to support multiple layouts, improved edge intersections, and new shapes思维导图渲染升级为支持多布局ELK 是其中之一、改进边交叉、新增形状。此版本把layout-elk从 patch 序列提升到 minor因为它开始承载 mindmap 的新布局能力。3.5 0.1.9对应 mermaid 11.10.0——模型顺序控制配置暴露两条记录共同构成一组能力elk.forceNodeModelOrder/elk.considerModelOrder暴露到 mermaid 配置feat默认行为改变ELK 不再强制按代码书写顺序排节点而是强烈参考该顺序make elk not force node model order, but strongly consider it instead。对应默认值forceNodeModelOrder: falseconsiderModelOrder: NODES_AND_EDGESdefaultConfig.ts。接线位置在根图选项render.tselk.layered.crossingMinimization.forceNodeModelOrder: data4Layout.config.elk?.forceNodeModelOrder, elk.layered.considerModelOrder.strategy: data4Layout.config.elk?.considerModelOrder,3.6 0.1.8对应 mermaid 11.7.0Make elk respect the order of nodes based from the code开始让 ELK 尊重源码中节点的声明顺序——这是 0.1.9 中模型顺序系列配置的前身先有硬尊重随后演进为可配置的 force/consider 两级策略。3.7 0.1.7 / 0.1.6对应 mermaid 11.4.x——菱形交点修复0.1.7更新处理交点时菱形diamond形状偏移量计算fix: Updated offset calculations for diamond shape when handling intersections0.1.6修复菱形形状在 ELK 渲染中的交点计算fix: Elk rendering of Diamond shape intersections。这两次修复针对的是边裁剪到节点边界阶段中菱形决策节点四边非轴平行导致的裁剪点错误。当前代码中该阶段对应 render.ts 的sanitizeElkEdgePoints/cutter2与 geometry.ts 中的形状交点计算函数computeNodeIntersection、replaceEndpoint等。3.8 0.1.5对应 mermaid 11.3.0chore: Update render options渲染选项更新为后续把 ELK 配置统一进data4Layout.config.elk命名空间做铺垫。3.9 0.1.4无对应 mermaid 依赖变更chore: fix render types修复渲染相关的类型定义。3.10 0.1.3对应 mermaid 11.1.0——默认配置更新 破环策略暴露fix: Updates to the default elk configuration feat: exposing cycleBreakingStrategy to the configuration so that it can be modified using the configuration.更新了 ELK 的默认 layoutOptions即今天createRootElkGraph中那组elk.layered.*默认项的雏形unnecessaryBendpoints: true、mergeHierarchyEdges: true、multiEdge.improveCuts等新增elk.cycleBreakingStrategy配置允许用户指定 layered 布局的破环策略如GREEDY_MODEL_ORDER/MODEL_ORDER接线点在 render.tselk.layered.cycleBreaking.strategy: data4Layout.config.elk?.cycleBreakingStrategy, // 源码注释中还列出了候选值 // elk.layered.cycleBreaking.strategy: GREEDY_MODEL_ORDER, // elk.layered.cycleBreaking.strategy: MODEL_ORDER,3.11 0.1.2 / 0.1.1对应 mermaid 11.0.20.1.2Fix type file path修复类型文件路径0.1.1fix: Types path修复types指向。这两次都是打包/类型声明路径修正标志着该包自 mermaid 11.0 起以独立 workspace 包形式对外发布。四、elk.* 配置参数全表结合源码解析综合 CHANGELOG 与 defaultConfig.ts、render.tselk配置命名空间下可写参数及其实时接线位置如下配置项默认值引入版本ELK 选项接线位置作用mergeEdgesfalse11.0 前已存在0.2.2 修复子图传播根图elk.layered.mergeEdges 子图同选项合并同一起止的多条边为一条减少视觉冗余nodePlacementStrategyBRANDES_KOEPF0.1.5 前后根图与子图nodePlacement.strategy节点坐标放置策略nodePlacementAlignmentNONE0.2.3根图与子图elk.layered.nodePlacement.bk.fixedAlignmentBK 策略下的固定对齐如FIRST/LAST等控制节点在层内贴边排列forceNodeModelOrderfalse0.1.9elk.layered.crossingMinimization.forceNodeModelOrder强制按声明顺序减少交叉牺牲交叉数最优性considerModelOrderNODES_AND_EDGES0.1.9elk.layered.considerModelOrder.strategy破交叉时强烈参考声明顺序的程度NODES_AND_EDGES/NODES/EDGES/NONEcycleBreakingStrategy由 JSON Schema 提供0.1.3elk.layered.cycleBreaking.strategy破环回边策略影响递归图的阅读方向keepEntryNodeOnTopfalse0.2.3命中节点上写elk.layered.layering.layerConstraint: FIRST把递归流入口节点钉在首层配置通过 frontmatterconfig: elk: {...}或mermaid.initialize({ elk: {...} })写入渲染时整体挂在data4Layout.config.elk上被 render.ts 读取schema 定义见 config.schema.yamlelk节点自 L118 起类型见 config.type.ts。4.1keepEntryNodeOnTop的算法细节这是 0.2.3 的核心特性其实现值得展开。elk.layered必须先破环才能给节点分层而其默认破环启发式是纯度数的没有入口概念——于是递归流程里第一个声明的节点可能被排到布局中部阅读顺序被打乱。render.ts 的findCyclicEntryNodes算法按parentId把节点分组即按容器/子图隔离组内保持声明顺序只用容器内部边、忽略自环统计每个节点的入度并用无向邻接表求出弱连通分量迭代 DFS若某分量中不存在入度为 0 的节点则该分量必然含环无环有向图的每个弱连通分量必有源节点于是提名该分量中声明顺序最靠前的节点作为入口有源的分量即无环部分不做任何提名布局保持原样——这保证了无环图零影响。随后applyCyclicEntryConstraintrender.ts只在keepEntryNodeOnTop为真时对命中节点写约束if (!data4Layout.config.elk?.keepEntryNodeOnTop) { return; // 默认关闭现有 ELK 图不受影响 } // ... elkNode.layoutOptions { ...elkNode.layoutOptions, elk.layered.layering.layerConstraint: FIRST, };五、渲染管线从 LayoutData 到 SVG 坐标render.ts 用主包提供的工厂函数装配出完整渲染器export const render createCommonLayoutRendererElkLayoutResult, ElkPreparedLayout({ prepareLayout: prepareLayoutForElk, runLayoutCore: runElkLayoutCore, paintOptions: { skipIntersect: true }, // 交点已由 ELK 自研裁剪处理 });完整调用链buildElkGraphFromLayoutDatarender.tscreateRootElkGraph构建根 ELK 图写入elk.algorithm由加载器注入如elk.layered/elk.stress、elk.direction经dir2ElkDirection把TB/TD→DOWN、LR→RIGHT、RL→LEFT、BT→UP及第四节所列全部根级 layoutOptionsaddSubGraphs按parentId建立父子查找表parentLookupDb供跨层级边与坐标偏移使用addVertices/addVertex递归把节点加入 ELK 图子图节点挂labelData标签实测宽高普通节点挂width/heightaddEdgesToElkGraph把 mermaid 边转换为 ELK 边边标签带edgeLabels.placement: CENTERconfigureSubgraphNodes为每个子图写buildSubgraphLayoutOptions子图可有自己的dir与elk.algorithm并设elk.hierarchyHandling: SEPARATE_CHILDREN独立布局子图内部并删除子图自身宽高让其由内容撑开configureCrossHierarchyEdges对父子不同的两端用 find-common-ancestor.ts 找最近公共祖先并沿祖先链设置elk.hierarchyHandling: INCLUDE_CHILDREN使跨子图边可以正确穿越层级容器applyCyclicEntryConstraint按 4.1 所述钉住递归入口runElkLayout调用new ELK().layout(graph)elkjs 打包版并支持 dev 构建下通过globalThis.__mermaidProfiler对layoutCore单独计时出错时打印完整 ELK 图便于排查applyElkLayoutResultapplyElkNodePositions递归回填坐标——子图坐标是相对父容器的需累加relX/relY偏移得到全局posX/posY节点中心取x width/2applyElkEdgeLayout取 ELK 返回的sections[0]起点/折点/终点叠加calcOffset公共祖先偏移换算到全局坐标再经sanitizeElkEdgePointscutter2裁剪到节点边界、组端点贴边检测、去重、无效点兜底与ensureEndMarkerSegmentLength保证箭头头段长度 ≥ 8px输出最终points并写curve rounded0.2.1 行为orderNodesForElkPaint绘制顺序上组子图先于普通节点组之间按嵌套深度升序保证子图背景先画、节点后画。六、验证方式e2e 用例目录仓库为 ELK 布局维护了完整的 e2e 快照用例可用于对照验证各版本行为流程图 ELK 用例e2e/diagrams/flowchart/elk/56 个.mmd覆盖嵌套子图、样式表达式、边裁剪2824-elk-clipping-of-edges.mmd、方向继承2050-elk-handling-of-different-rendering-direction-in-subgraphs.mmd等场景类图 ELK 用例e2e/diagrams/class-diagram/elk/60 个.mmd快照测试入口e2e/helpers/mmd-snapshots.ts、e2e/helpers/mmd-snapshots.spec.ts包自身的单元测试packages/mermaid-layout-elk/src/tests/render.spec.ts针对布局核心函数、geometry.spec.ts边界交点几何。七、实践要点小结接入前提ELK 不随 mermaid 主包默认提供宿主环境必须npm install mermaid-js/layout-elk并registerLayoutLoaders否则layout: elk不生效peer 要求mermaid ^11.0.2。默认行为0.2.3 起elk别名 elk.layered分层布局边默认rounded圆角折线节点顺序强烈参考声明序而非强制mergeEdges、keepEntryNodeOnTop默认关闭属纯 opt-in增强不改变存量图。调参路径全局elk.*配置 → 根图 layoutOptions子图内部则经buildSubgraphLayoutOptions传播0.2.2 修复后mergeEdges对子图内边同样生效。递归流程阅读顺序问题用keepEntryNodeOnTop: true解决层内排列不齐可用nodePlacementAlignment/nodePlacementStrategy调整回边方向不佳可用cycleBreakingStrategy换破环策略。可追溯性每条行为都能对上 CHANGELOG 条目与源码位置CHANGELOG、render.ts、defaultConfig.ts配合 e2e.mmd快照即可复现验证。【免费下载链接】mermaidGeneration of diagrams like flowcharts or sequence diagrams from text in a similar manner as markdown项目地址: https://gitcode.com/GitHub_Trending/me/mermaid创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门