资讯动态

Mermaid User Journey 用户旅程图实战:从语法、评分机制到源码渲染全解

发布时间:2026/9/7 18:02:12 来源:尧图企业网站定制
Mermaid User Journey 用户旅程图实战从语法、评分机制到源码渲染全解【免费下载链接】mermaidGeneration of diagrams like flowcharts or sequence diagrams from text in a similar manner as markdown项目地址: https://gitcode.com/GitHub_Trending/me/mermaidMermaid 的 User Journey Diagram用户旅程图用journey语法块以分区 任务 评分 参与角色的方式可视化用户在完成某个具体任务时所经历的每一步及其满意度。本文以官方语法文档 docs/syntax/userJourney.md 为主线完整继承其中的语法规则与示例并结合packages/mermaid/src/diagrams/user-journey/下的解析器、数据模型与渲染器源码讲清每个语法元素在底层是如何被解析、存储和绘制成 SVG 的读完即可独立编写、配置并排错用户旅程图。一、User Journey 图解决什么问题按官方文档的定义引自 packages/mermaid/src/docs/syntax/userJourney.mdUser journeys describe at a high level of detail exactly what steps different users take to complete a specific task within a system, application or website. This technique shows the current (as-is) user workflow, and reveals areas of improvement for the to-be workflow.即用户旅程图用于描述用户完成任务的步骤展示现状as-is工作流并帮助发现改进目标to-be流程的机会。Mermaid 中的典型示例为这张图由三层结构组成title标题、若干section分区、以及分区下的若干任务行。每个任务行携带一个 15 的评分和若干参与角色。二、语法详解2.1 基本规则一个用户旅程图被拆分为若干section分区每个分区描述用户正在尝试完成的任务片段任务行的完整语法为Task name: score: comma separated list of actors其中Task name是任务名称score是评分comma separated list of actors是逗号分隔的参与角色列表Score 是 15 的整数含边界代表该步骤的用户体验好坏。2.2 语法的底层定义Jison 文法从源码结构看journey类型的词法与语法由 journey.jison 定义其中 statement 产生式第 6067 行完整枚举了一行语句可以是哪几类内容statement : title {yy.setDiagramTitle($1.substr(6));$$$1.substr(6);} | acc_title acc_title_value { $$$2.trim();yy.setAccTitle($$); } | acc_descr acc_descr_value { $$$2.trim();yy.setAccDescription($$); } | acc_descr_multiline_value { $$$1.trim();yy.setAccDescription($$); } | section {yy.addSection($1.substr(8));$$$1.substr(8);} | taskName taskData {yy.addTask($1, $2);$$task;}由此可以确认几个官方语法文档之外的细节title与section的文本会被裁剪substr(6)与substr(8)分别去掉前缀title/section关键字本身及其后的空白支持无障碍指令词法部分定义了accTitle:...与accDescr:...含accDescr:{...}多行形式可分别为图表设置无障碍标题与描述注释支持词法规则\%%(?!\{)[^\n]*、[^\}]\%\%[^\n]*与\#[^\n]*表示%%行尾注释和#注释均可使用任务行的taskName匹配[^#:\n;]taskData匹配:[^#\n;]——因此任务名中不能出现:、;、#而评分/角色部分恰好以冒号开头、且角色名中同样不能出现这些分隔符。2.3 评分与角色都是什么任务行的解析在数据模型 journeyDb.js 的addTask中完成export const addTask function (descr, taskData) { const pieces taskData.substr(1).split(:); let score 0; let peeps []; if (pieces.length 1) { score Number(pieces[0]); peeps []; } else { score Number(pieces[0]); peeps pieces[1].split(,); } const peopleList peeps.map((s) s.trim()); // ... 存入 rawTasks };这里有两个可直接落地的结论角色列表是可选的若只写Do work: 1只有评分、没有冒号后的角色pieces.length 1分支会令peeps []任务照常记录评分经Number()转换后存入score角色经split(,)并逐项trim()得到因此Me, Cat中逗号后的空格不会污染角色名。角色汇总逻辑在同文件的updateActors第 4959 行把所有任务的people合并进数组用Set去重后sort()排序。也就是说图例中的角色顺序是按字典序排列的与图中首次出现顺序无关。三、渲染管线评分如何变成表情分区如何着色渲染入口在 journeyDiagram.ts 中组装parserJison、dbjourneyDb、rendererjourneyRenderer、styles四件套init阶段用cnf.journey配置刷新渲染器并清空数据。3.1 角色图例与左边缘journeyRenderer.ts 的draw函数先取出db.getActors()为每个角色按序分配conf.actorColours调色板中的颜色循环取色随后调用drawActorLegend在左侧绘制圆点 角色名图例并把绘图区左边缘设为leftMargin maxWidth。角色名过宽时会按maxLabelWidth自动折行见drawActorLegend中的测量与断行逻辑。e2e 测试 journey.spec.js 验证了默认左边缘行为设置maxLabelWidth: 320后第一个任务文本的x坐标与 150px 的偏差应 ≤2px对应配置项leftMargin的默认值 150。3.2 评分 → 表情脸每个任务会画一个表情脸逻辑在 svgDraw.js 的drawFace中if (faceData.score 3) { smile(face); // 分数大于 3微笑 } else if (faceData.score 3) { sad(face); // 分数小于 3悲伤 } else { ambivalent(face); // 分数等于 3无表情直线嘴 }即5/4 分是笑脸2/1 分是哭脸3 分是平嘴嘴部弧线用 d3 的arc生成。同时脸在任务虚线上的垂直位置由公式cy 300 (5 - score) * 30决定drawTask分数越高脸越靠上分数每低 1 分脸就向下垂30px直观呈现满意度落差。3.3 分区色带与任务框drawTasksjourneyRenderer.ts按任务顺序遍历当任务所属 section 变化时取fills[sectionNumber % fills.length]与textColours[sectionNumber % textColours.length]给该分区选色并统计该分区内连续任务数taskInSectionCount用于计算分区背景宽度conf.width * taskCount conf.diagramMarginX * (taskCount - 1)见 drawSection。任务框内还会在左上角为每个参与角色绘制带title悬浮提示的小圆点drawTask颜色与图例一致。3.4 底部活动线与文本换行所有任务下方有一条贯穿全图、带箭头的粗黑活动线journeyRenderer.ts箭头 marker 由initGraphics注册任务文本的排布方式由textPlacement配置决定foforeignObject默认、tspan、old三种svgDraw.js。在tspan模式下任务名中的br会被content.split(/br\s*\/?/gi)拆成多行居中对齐渲染因此任务名支持用br换行。四、配置项与默认值User Journey 图的专属配置类型是JourneyDiagramConfig定义见 config.type.ts默认值与约束见 config.schema.yaml 中JourneyDiagramConfig的$defs。核心项及默认值汇总如下配置项含义默认值diagramMarginX/diagramMarginY图表左右 / 上下外边距50 / 10leftMargin左侧角色图例区宽度基线Margin between actors150maxLabelWidth角色名最大宽度超过即折行360width/height任务框 / 分区头高度150 / 50boxMargin/boxTextMargin/noteMargin各类框体与文本间距10 / 5 / 10taskMargin任务之间的水平间距task.x i * taskMargin i * width leftMargin50taskFontSize/taskFontFamily任务文本字号 / 字体14 /Open Sans, sans-seriftextPlacement文本排布方式tspan/fo/oldfoactorColours角色圆点配色按序循环[#8FBC8F, #7CFC00, #00FFFF, #20B2AA, #B0E0E6, #FFFFE0]sectionFills分区背景色按序循环[#191970, #8B008B, #4B0082, #2F4F4F, #800000, #8B4513, #00008B]sectionColours分区标题文字颜色[#fff]titleColor/titleFontFamily/titleFontSize标题文字颜色 / 字体 / 字号/trebuchet ms, verdana, arial, sans-serif/4ex继承自基础配置的useMaxWidth默认为true。e2e 快照用例 should-render-a-user-journey-diagram-when-usemaxwidth-is-false.mmd 展示了通过 frontmatter 覆盖该配置的方式--- config: journey: useMaxWidth: false --- journey title E-Commerce section Order from website Add to cart: 5: Me section Checkout from website Add payment details: 5: Me对应断言见 journey.spec.jsuseMaxWidth: true时 SVG 的width属性为100%且style中max-width为 700px。五、完整示例与验证素材下面给出一个覆盖标题、多分区、多角色与不同评分区间的完整示例可放入任意支持 Mermaid 的 Markdown 环境直接渲染其中注册分区内两个任务会共用同一背景色首次使用换用下一循环色角色按字典序导师、新用户、访客出现在左侧图例。仓库中可直接查看的验证素材e2e 快照用例e2e/diagrams/journey/ 下的 simple-test.mmd、should-render-a-user-journey-chart.mmd渲染行为测试e2e/rendering/user-journey/journey.spec.js语法单测journey.spec.jsparser 目录 与 journeyDb.spec.js。六、小结语法骨架journeytitle 若干section 任务行任务名: 1-5分: 角色A, 角色B评分必须为 15 的整数角色列表可省略视觉语义由源码固化3 分微笑、3 分悲伤、3 分平嘴分数越低脸越靠下分区背景色按sectionFills循环取色角色配色按actorColours循环取色并按字典序排布图例排版与尺寸由JourneyDiagramConfig控制width、taskMargin、leftMargin、maxLabelWidth、textPlacement等可通过mermaid.initialize、mermaidAPI配置或 frontmatter 中config.journey覆盖任务名中避免:、;、#等与解析器冲突的字符需要换行时在任务名中使用br。【免费下载链接】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),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价