[{"data":1,"prerenderedAt":7},["ShallowReactive",2],{"example-markdown-content:zh:line-shapes-junctions-and-custom-arrows":3},{"markdown":4,"isPaidExample":5,"isTruncated":5,"charLimit":6},"# 在一个参考图中展示线条形状、连接点锚位与自定义箭头\n\n## 这个示例构建了什么\n\n该示例构建了一个全高的 `relation-graph` 画布，用作线条渲染的可视化参考板。查看者会看到一个预先排好的中心布局图，其中包含通用的字母节点，以及大量带注释的连接线，在同一画面中对比线宽、线条形状、连接点位置、箭头可见性、文本放置方式和颜色处理。\n\n用户不会编辑图结构，但可以查看这个预设的对照面板、切换深色主题、打开悬浮设置面板、更改滚轮和拖拽行为，并将画布导出为图片。这个示例的重点在于覆盖面广：它会同时展示许多内置线条选项，然后再通过 CSS 标签样式和自定义 SVG 箭头标记对其进行扩展。\n\n## 数据是如何组织的\n\n图数据在 `initializeGraph()` 中以内联方式声明为一个 `RGJsonData` 对象，包含 `rootId: 'a'`、22 个节点和 28 条线。`setJsonData()` 之前没有预处理步骤。这个示例直接在代码中构造最终数据集，并按原样加载。\n\n大部分语义都放在 `lines` 数组中。每条边记录都可以携带自己的 `lineShape`、`lineWidth`、`color`、`fontColor`、`showStartArrow`、`showEndArrow`、`startMarkerId`、`endMarkerId`、`fromJunctionPoint`、`toJunctionPoint`、`useTextOnPath` 和 `className`。节点数据大多只是用于承载对比布局的占位内容，不过也有少数节点会覆盖尺寸、形状或固定位置。在真实产品中，同样的数据结构可以表示工作流分支、集成路径、血缘边、依赖连接，或需要为每条连接单独指定渲染规则的带注释网络路径。\n\n## 如何使用 relation-graph\n\n`index.tsx` 用 `RGProvider` 包裹这个 demo，`MyGraph.tsx` 则通过 `RGHooks.useGraphInstance()` 获取当前图实例。图使用内置的 `center` 布局，并显式设置了 `levelGaps`、圆形节点默认值、60x60 的默认节点尺寸，以及白色默认节点颜色。\n\n图会在挂载时加载一次。`initializeGraph()` 会调用 `setJsonData()`，然后执行 `moveToCenter()` 和 `zoomToFit()`，让这个预设画廊在初始状态下就完整可见。这个示例没有使用节点插槽、线条插槽、画布插槽或编辑 API，而是把大部分变化都放进内置的线条元数据字段中。\n\n在内置渲染器之上，这个示例还叠加了两种非数据层面的自定义方式。`MyLineArrowDefine` 会注入 SVG `\u003Cmarker>` 定义，让选中的线条可以通过 marker id 使用自定义的起始和结束箭头。局部 SCSS 文件则通过每条线的类名（如 `.my-text-bg-001` 到 `.my-text-bg-004`）来样式化内置线条标签，而当勾选框启用时，外层包裹类会切换为 `.my-graph-dark`，从而重新定义画布、线条文本、节点和工具栏的样式。\n\n悬浮帮助窗口来自一个共享的本地组件，但它也是示例渲染结果的一部分。这个辅助组件会使用 `RGHooks.useGraphStore()` 读取当前交互模式，使用 `graphInstance.setOptions()` 切换滚轮和拖拽行为，并通过 `prepareForImageGeneration()` 与 `restoreAfterImageGeneration()` 将当前图视图导出为图片。\n\n## 关键交互\n\n最显眼的交互，是悬浮说明窗口中的本地深色主题切换。它不会更改图数据，但会改变同一组线条样式在浅色和深色背景下的视觉表现。\n\n悬浮帮助窗口中的设置面板为图增加了操作层控制。用户可以把滚轮事件切换为滚动或缩放，把画布拖拽切换为框选或移动，也可以下载当前画布的图片。这些控件影响的是查看环境，而不是图结构本身。\n\n说明窗口本身也可以通过其内置辅助控件进行拖拽、最小化和重新打开。节点点击和线条点击事件虽然已绑定，但它们只是在控制台打印对象，因此更像是调试或查看用的检查钩子，而不是有实际业务意义的终端用户流程。\n\n## 关键代码片段\n\n这段代码表明，整个场景使用了 relation-graph 的内置中心布局和默认节点选项。\n\n```tsx\nconst graphOptions: RGOptions = {\n    defaultNodeShape: RGNodeShape.circle,\n    defaultNodeBorderWidth: 1,\n    defaultNodeWidth: 60,\n    defaultNodeHeight: 60,\n    defaultNodeColor: '#ffffff',\n    layout: {\n        layoutName: 'center',\n        levelGaps: [300, 200, 200]\n    }\n};\n```\n\n这段代码表明，大部分可见差异都是直接在每条线记录中表达的。\n\n```tsx\n{ id: 'line-2', from: 'a', to: 'c', text: 'useTextOnPath Line 1', useTextOnPath: true, fontSize: 10, color: 'rgba(30, 144, 255, 1)' },\n{ id: 'line-5', from: 'a', to: 'd', text: 'Thick Line', lineWidth: 3 },\n{ id: 'line-6', from: 'a', to: 'e', text: 'Hide Arrow', showEndArrow: false },\n{ id: 'line-11', from: 'a', to: 'd', text: 'Polyline', lineShape: RGLineShape.StandardOrthogonal, fromJunctionPoint: RGJunctionPoint.left, toJunctionPoint: RGJunctionPoint.top, className: 'my-text-bg-001' },\n```\n\n这段代码表明，部分线条会附加自定义 marker id，而不只是依赖默认箭头。\n\n```tsx\n{ id: 'line-18', from: 'c', to: 'm1', text: 'RGJunctionPoint.bottom', endMarkerId: 'my-arrow-001', startMarkerId: 'my-arrow-001-start', showStartArrow: true, lineShape: RGLineShape.StandardCurve, toJunctionPoint: RGJunctionPoint.bottom, lineWidth: 6, color: '#00ced1' },\n{ id: 'line-19', from: 'c', to: 'm2', text: 'Custom Line Arrow', endMarkerId: 'my-arrow-001', startMarkerId: 'my-arrow-001-start', showStartArrow: true, lineShape: RGLineShape.StandardCurve, fromJunctionPoint: RGJunctionPoint.border, lineWidth: 7, color: '#00ced1' },\n```\n\n这段代码展示了隐藏的 SVG 定义，它们使这些自定义 marker id 可供图渲染器使用。\n\n```tsx\n\u003Csvg className=\"absolute opacity-0\" xmlns=\"http://www.w3.org/2000/svg\">\n    \u003Cdefs>\n        \u003Cmarker id=\"my-arrow-001\" markerWidth=\"80\" markerHeight=\"80\" refX=\"2\" refY=\"3\"\n            markerUnits=\"userSpaceOnUse\" orient=\"auto\" viewBox=\"0 0 12 12\">\n            \u003Cpath d=\"M 4 6, V 0, L 0 3, Z\" style={{ fill: 'context-stroke' }}>\u003C/path>\n        \u003C/marker>\n        \u003Cmarker id=\"my-arrow-001-start\" markerWidth=\"80\" markerHeight=\"80\" refX=\"2\" refY=\"3\"\n            markerUnits=\"userSpaceOnUse\" orient=\"auto-start-reverse\" viewBox=\"0 0 12 12\">\n            \u003Cpath d=\"M 4 6, V 0, L 0 3, Z\" style={{ fill: 'context-stroke' }}>\u003C/path>\n        \u003C/marker>\n    \u003C/defs>\n\u003C/svg>\n```\n\n这段代码表明，标签展示也通过 CSS 类和深色主题包裹类进行了自定义。\n\n```scss\n.my-text-bg-003 {\n    .rg-line-label {\n        background-color: rgb(13, 179, 1);\n        color: #ffffff;\n        border-radius: 20px;\n        padding: 3px 10px;\n    }\n}\n\n.my-graph-dark {\n    .relation-graph {\n        .rg-map {\n            background-color: #333;\n        }\n    }\n}\n```\n\n这段代码表明，共享帮助窗口会通过 relation-graph API 切换图的交互模式。\n\n```tsx\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从这组对比数据可以看出，这个示例的突出之处在于：一个静态的中心布局图把许多内置线条行为集中展示在同一个地方，包括混合线条形状、显式连接点锚位、宽度变化、隐藏或反向箭头、沿路径排布的文本标签、自定义 marker id，以及按线条分类的标签类。它的独特价值不在于某一项技巧是独有的，而在于它把这么多能力组合进了同一个预设参考板中。\n\n与 `advanced-line-usage` 相比，这个示例更宽、更密。两个 demo 都使用内联数据，并且点击处理器都只输出到控制台，但 `line` 增加了更多可见变体、自定义 SVG marker 定义、深色主题切换，以及悬浮工具窗口。与 `custom-line-style` 相比，区别在于实现方式：`custom-line-style` 强调运行时的批量重设样式，而这个示例则从一开始就通过每条边的数据和 CSS 类，同时展示大部分变化。\n\n与 `line-style1` 和 `layout-center` 相比，这个示例较少强调某一种狭义的预设线条族或整图级展示控制，而更强调把一个预设数据集当作广义的边行为展示板来使用。当团队想先对比 relation-graph 的内置线条能力，再决定是否进入自定义线条插槽或完整编辑器时，它会是一个很强的起点。\n\n## 这种模式还适用于哪里\n\n这种模式很适合迁移到那些“连接本身承载多重含义”的产品场景中。团队可以把它改造成用于工作流分支、依赖方向、网络路由、集成连接或血缘路径的 QA 面板，让每条边通过不同的宽度、箭头、锚位或标签规则来表达状态或语义。\n\n它也适合作为内部文档。在设计自定义渲染器之前，团队可以先构建一个像这样紧凑的参考图，用来判断哪些需求已经被 relation-graph 的内置线条字段、CSS 主题能力和注入式 SVG marker 所覆盖。在培训材料中，同样的结构也可以作为可复用的边配置选项可视化目录。\n",false,500,1782615374039]