[{"data":1,"prerenderedAt":7},["ShallowReactive",2],{"example-markdown-content:zh:animated-route-progress-line-slot":3},{"markdown":4,"isPaidExample":5,"isTruncated":5,"charLimit":6},"# 带 Checked 状态指标的自定义路径进度线槽位\n\n## 这个示例构建了什么\n\n这个示例构建了一个从左到右展开的路径树，看起来更像运输或流程监控看板，而不是默认图谱。每条线都会变成一条加粗的动态路径，路径上有一个移动的小圆点、一个沿计算路径定位的交通工具 emoji，以及一张在连线被 checked 时展开的标签卡片。\n\n用户可以查看连线、点击移动标记或标签，同时不影响 relation-graph 原本的连线事件流；还可以打开连线专属的 `Detail` 操作、拖动或最小化浮动帮助窗口、切换画布交互模式，并将图谱导出为图片。这个示例的重点在于：每条线上的元数据同时驱动动画效果和详情展开，而布局、路径几何以及连线状态管理依然由 relation-graph 负责。\n\n## 数据是如何组织的\n\n图数据以内联 `RGJsonData` 的形式声明，包含 `rootId`、`nodes` 和 `lines`。每条线仍然使用 relation-graph 标准的 `from` 和 `to` 结构，但同时还携带一个 `data` 对象，其中包含 `myIcon`、`myCapacity`、`myWeight`、`mySpeed` 和 `myPercent`。这部分载荷才是示例的核心内容：它决定显示哪种交通工具标记、标记有多大、白色小圆点移动得多快，以及高亮路径已经推进了多远。\n\n在调用 `setJsonData` 之前，还有一个很小的预处理步骤：每条线都设置 `showEndArrow = false`。这样可以让路径展示更接近被监控的轨道，而不是带箭头的方向连接线。在真实应用里，只要每条连接都能提供一个进度值和少量指标，同样的形态也可以表示货运路线、流程传输线、管道状态、服务流量或机器流转路径。\n\n## relation-graph 是如何使用的\n\n`RGProvider` 包裹整个示例，以便 hooks 可以获取当前活动的图实例。`RelationGraph` 被配置为从左侧生长的树形布局，`levelGaps` 为 `[500, 400]`，同时使用 `RGJunctionPoint.lr` 和 `RGLineShape.StandardCurve`。这些默认项让路径几何足够可预测，便于做沿路径运动的动画。\n\n关键扩展点是 `RGSlotOnLine`。`MyGraph` 会把运行时的连线 slot props 传给 `MyLineContent`，同时再添加一个来自父组件的 `Detail` 操作回调。在 `MyLineContent` 内部，`RGHooks.useGraphInstance()` 会调用 `generateLinePath` 获取真实的 SVG 路径，调用 `generateLineTextStyle` 复用 relation-graph 计算出的标签定位样式，并调用 `onLineClick` 把自定义 SVG 或 HTML 上的点击继续转发回 relation-graph 的连线事件管线。\n\n这个 slot 没有把 relation-graph 的原语绕开，而是继续把它们保留在渲染链路里。`RGLinePath` 负责渲染实际的 SVG 路径，并接收转发后的点击处理器。`RGLineText` 在连线处于 div-text 分支时渲染 HTML 标签容器。外层的 `\u003Cg>` 会写入一些 CSS 变量，例如路径本身、总长度、已移动长度、已移动百分比和速度，样式表再通过 `stroke-dasharray` 和 `offset-path` 消费这些变量，来驱动描边、白色小圆点和 emoji 标记的动画。\n\n这个示例还把自定义连线 slot 与 `RGSlotOnNode` 组合使用，用圆形仓库图标节点替换默认节点主体。在图谱主体之外，图实例 API 通过 `setJsonData`、`moveToCenter` 和 `zoomToFit` 来加载并框定数据集。共享的 `DraggableWindow` 浮层使用 `RGHooks.useGraphStore()` 和 `setOptions(...)` 切换滚轮与拖拽行为，然后结合 `prepareForImageGeneration()`、`restoreAfterImageGeneration()` 以及 `modern-screenshot` 导出图谱画布。\n\n## 关键交互\n\n- 点击自定义 SVG 路径、emoji 标记或 HTML 标签时，仍然会转发到 relation-graph 的 `onLineClick` 处理流程。\n- 更丰富的指标区块默认隐藏，只有当连线进入 checked 状态时才会显示。\n- `Detail` 按钮会把当前 `RGLine` 回调给父组件，并弹出该连线专属的提示框。\n- 浮动覆盖层可以拖动、最小化、切换到设置面板，并用于导出图片。\n- 设置面板可以在不重新加载图谱的情况下修改滚轮行为和画布拖拽行为。\n\n## 关键代码片段\n\n下面这段代码展示了从左到右的树形布局，以及自定义渲染器所依赖的默认连线设置。\n\n```tsx\nconst graphOptions: RGOptions = {\n    defaultJunctionPoint: RGJunctionPoint.lr,\n    defaultLineShape: RGLineShape.StandardCurve,\n    layout: {\n        layoutName: 'tree',\n        from: 'left',\n        levelGaps: [500, 400]\n    }\n};\n```\n\n下面这段代码展示了每条路径线都会携带自己的图标、容量、重量、速度和进度数据，然后再统一关闭默认终点箭头。\n\n```tsx\nlines: [\n    { id: 'l1', from: 'base', to: '1', text: 'Line X01', data: { myIcon: '🚢', myCapacity: 1.2, myWeight: 1, mySpeed: 1, myPercent: 0.2 } },\n    { id: 'l2', from: 'base', to: '2', text: 'Line X02', data: { myIcon: '🚢', myCapacity: 2, myWeight: 1.8, mySpeed: 0.3, myPercent: 0.8 } },\n    // ...\n]\nmyJsonData.lines.forEach((line) => {\n    line.showEndArrow = false;\n});\nawait graphInstance.setJsonData(myJsonData);\n```\n\n下面这段代码展示了图谱如何同时接入自定义连线 slot 和第二个自定义节点 slot。\n\n```tsx\n\u003CRelationGraph\n    options={graphOptions}\n    onLineClick={onLineClick}\n>\n    \u003CRGSlotOnLine>\n        {(lineSlotProps: RGLineSlotProps) => (\n            \u003CMyLineContent\n                {...lineSlotProps}\n                onMyLineDetailClick={onMyLineDetailClick}\n            />\n        )}\n    \u003C/RGSlotOnLine>\n    \u003CRGSlotOnNode>\n```\n\n下面这段代码展示了连线 slot 如何推导真实路径几何，并把路径元数据转换成用于动画和 checked 状态样式的 CSS 变量。\n\n```tsx\nconst linePathInfo = useMemo\u003CRGLinePathInfo>(() => graphInstance.generateLinePath(lineConfig), [lineConfig]);\nconst textStyle = graphInstance.generateLineTextStyle(lineConfig, linePathInfo);\nconst pathEl = document.createElementNS('http://www.w3.org/2000/svg', 'path');\npathEl.setAttribute('d', linePathInfo.pathData);\nconst pathLength = pathEl.getTotalLength();\nreturn (\u003Cg\n    style={{\n        '--my-line-path': `path('${linePathInfo.pathData}')`,\n        '--my-line-path-length': pathLength + 'px',\n        '--my-moved-length': (pathLength * lineConfig.line.data?.myPercent) + 'px',\n        '--my-moved-percent': lineConfig.line.data?.myPercent * 100 + '%',\n        '--my-speed': ((1 / lineConfig.line.data?.mySpeed) * 0.5) + 's'\n    }}>\n```\n\n下面这段代码展示了该 slot 如何保留 `RGLinePath`，同时额外添加一个移动小圆点和一个会随大小变化的交通工具标记，并让它们沿路径放置。\n\n```tsx\n\u003CRGLinePath\n    lineConfig={lineConfig}\n    linePathInfo={linePathInfo}\n    useTextOnPath={useSvgTextPath}\n    checked={checked}\n    graphInstanceId={graphInstanceId}\n    onLineClick={onLineClick}\n>\n    \u003Cg>\n        \u003Ccircle className=\"my-dot\" r=\"3\">\u003C/circle>\n        \u003Cg className=\"my-container\">\n            \u003Ctext onClick={onLineClick} fontSize={(lineConfig.line.data?.myWeight || 1) * 20 + 15} y={-5} transform=\"scale(-1, 1)\">{lineConfig.line.data?.myIcon}\u003C/text>\n        \u003C/g>\n    \u003C/g>\n\u003C/RGLinePath>\n```\n\n下面这段代码展示了 HTML 标签分支如何渲染路径指标，以及一个由父组件处理的详情操作。\n\n```tsx\n\u003Cdiv className=\"my-text\">\n    \u003Cdiv>Cap: {lineConfig.line.data?.myCapacity.toFixed(1)}\u003C/div>\n    \u003Cdiv>Weight: {lineConfig.line.data?.myWeight.toFixed(1)}\u003C/div>\n    \u003Cdiv>Speed: {lineConfig.line.data?.mySpeed.toFixed(1)}\u003C/div>\n\u003C/div>\n\u003Cbutton\n    className=\"cursor-pointer hover:underline bg-blue-600 text-white py-1 px-3 rounded mt-2\"\n    onClick={() => { onMyLineDetailClick(lineConfig.line); }}\n>\n    Detail\n\u003C/button>\n```\n\n下面这段代码展示了这条 CSS 规则如何让指标卡片在连线被 checked 之前保持隐藏。\n\n```scss\n.rg-line-peel.rg-line-checked {\n    .rg-line-label {\n        display: block;\n        background-color: rgb(255, 0, 150);\n        color: #fff;\n    }\n\n    .my-text {\n        display: block;\n    }\n}\n```\n\n下面这段代码展示了共享的查看器工具面板如何修改画布行为，并对准备好的图谱 DOM 执行图片导出。\n\n```tsx\nconst { options } = RGHooks.useGraphStore();\nconst dragMode = options.dragEventAction;\nconst wheelMode = options.wheelEventAction;\n\n\u003CSettingRow\n    label=\"Wheel Event:\"\n    options={[\n        { label: 'Scroll', value: 'scroll' },\n        { label: 'Zoom', value: 'zoom' },\n        { label: 'None', value: 'none' },\n    ]}\n    value={wheelMode}\n    onChange={(newValue: string) => { graphInstance.setOptions({ wheelEventAction: newValue }); }}\n/>\n```\n\n## 这个示例的独特之处\n\n对比数据把这个示例定位为附近几个自定义连线 slot 示例中状态信息最丰富的一个。它最强的区分点在于：它把每条线上的元数据转换成路径进度渲染，并在同一个自定义渲染器里组合使用 `RGSlotOnLine`、`generateLinePath`、`generateLineTextStyle`、`RGLinePath` 和 `RGLineText`。在这个基础上，它又进一步利用同一份元数据控制标记图标、标记大小、绘制距离和动画速度。\n\n相比 `adv-line-slot-1`，这个变体更偏向数据驱动。它不只是停留在通用的移动小圆点和简单详情链接上，而是加入了 `myPercent`、仅在 checked 时显示的路径指标，以及协同设计的节点样式。相比 `adv-line-slot`，它把重心从端点注释转移到了路径本身的受监控进度上。相比 `line`，这种差异就更加明显了：这个示例替换了连线渲染器并测量生成出的路径，而不是停留在 relation-graph 内置连线选项展示的范围内。\n\n这里的自定义节点 slot 也很重要，但它是次要的。对比记录已经明确说明，真正的重点是 checked 连线检查与基于路径的路线动画，而不是一个面向广泛节点样式的展示示例。\n\n## 这种模式还适用于哪里\n\n这种模式很适合迁移到物流跟踪、仓储流转监控、管道状态看板、基础设施流动视图、服务流量地图以及生产路由仪表板中。尤其是在每条连接都需要直接在线上展示进度、速度或负载，同时又希望图谱保持只读，并继续保留 relation-graph 内置布局与事件处理能力时，这种模式会非常有用。\n",false,500,1782615379539]