最短路径查询
这个示例加载人物关系图,从实时 relation-graph 实例中提取可搜索端点选项,并允许用户查询两个选定节点之间的最短连接。随后它将结果映射回画布:弱化无关节点与连线,同时加粗活动路径,并放在可拖拽工具窗中操作。
实时关系图上的最短路径查询
本示例构建的内容
这个示例在一个已经渲染完成的人物关系图之上构建了一个关系路径探索器。用户会看到一个由头像节点和带标签关系线组成的力导向画布,以及一个悬浮的白色查询窗口,用户可以在其中选择起始人物和目标人物。
当两个端点都被选中后,示例会从实时的 relation-graph 实例中计算最短连接路径,并将结果应用回当前画布。当前路径会保持高亮,无关节点和连线会淡化为较低透明度,而同一个悬浮窗口还提供共享的画布设置和图片导出功能。
数据如何组织
加载后的图数据遵循 RGJsonData 结构,包含 rootId、nodes 数组和 lines 数组。每个节点都带有 id、显示文本、边框和填充颜色,以及存放在 data.icon 中的头像 URL。每条连线保存其两端节点、诸如 teacher-student 或 relative 这样的关系标签、显示颜色,以及放在 data.type 中的语义类型。
在调用 setJsonData() 之前几乎没有做预处理:fetchJsonData() 只是在短暂超时后返回本地数据集。第一个真正有意义的转换发生在图挂载完成之后,此时 initializeGraph() 会读取 graphInstance.getNodes(),并将实时节点集合转换为查询表单中的选择项。在每次查询期间,代码都会通过 getLinks() 构建一个临时辅助图,这样路径搜索就是基于当前已渲染图状态进行,而不是依赖一个独立的并行模型。
在业务应用中,同样的结构可以表示员工关系、账户到账户的调查链路、客户影响网络,或服务依赖关系。只要节点 id 保持稳定,并且每个已渲染节点都暴露面向用户的标签,这个路径查询面板就可以继续工作。
relation-graph 的用法
页面包裹在 RGProvider 中,主组件通过 RGHooks.useGraphInstance() 获取实时实例。图本身使用力导向布局,配置包括 layoutName: 'force'、force_node_repulsion: 0.5 和 maxLayoutTimes: 50,同时配合直线连线、圆形节点、沿路径渲染的连线文字、20 的 multiLineDistance,以及位于右下角的纵向工具栏。
这个示例将图视为一个带运行时分析能力的查看器,而不是编辑器。加载完成后,它会在实例上依次调用 loading()、setJsonData()、clearLoading()、moveToCenter() 和 zoomToFit()。执行路径查询时,它会读取 getNodes()、getLinks() 和 getLines(),然后使用 updateNode() 与 updateLine() 清除之前的样式、淡化非路径元素,并标记当前激活路径。
自定义渲染通过 RGSlotOnNode 实现,它将默认节点主体替换为圆形头像和下方标签。样式扩展主要放在 my-relation-graph.scss 中,尤其包括连线标签徽标、选中态高亮,以及更粗的路径高亮线。悬浮的 DraggableWindow 则带来了一层辅助工具界面:它可以被拖动、最小化、切换到设置面板,并通过在同一实时图上下文中调用 prepareForImageGeneration()、getOptions()、setOptions() 和 restoreAfterImageGeneration() 来导出图片。
关键交互
- 用户在起点和终点输入框中输入内容以筛选节点名称,然后从下拉列表中选择具体节点。
- 在两个端点都被选中之前,查询按钮会保持禁用;如果用户只输入了部分内容但尚未完成选择,该输入会被染成红色,以提示选择尚未完成。
- 提交表单后,会基于当前图状态重新计算路径并重绘高亮,而不是重新构建整个数据集。
- 非路径节点和连线会被淡化而不是隐藏,因此选中的路径仍然能在原始图上下文中保持可读。
- 点击空白画布会清除 relation-graph 的 checked-state 高亮,而下一次最短路径查询会在应用新结果之前重置路径类名和透明度。
- 悬浮工具窗口支持拖动、最小化、打开设置叠层,以及将当前画布导出为图片。
关键代码片段
这段初始化代码说明图会先完成加载,然后复用实时节点列表来填充查询表单。
const initializeGraph = async () => {
const myJsonData: RGJsonData = await fetchJsonData();
graphInstance.loading();
await graphInstance.setJsonData(myJsonData);
graphInstance.clearLoading();
graphInstance.moveToCenter();
graphInstance.zoomToFit();
setNodeItems(graphInstance.getNodes().map(n => ({text: n.text || '', value: n.id})));
};
这个辅助函数证明,最短路径计算是从当前的 relation-graph 实例派生出来的,而不是来自另一个仅用于渲染的数据集。
export const calcShortestPath = (fromNodeId: string, toNodeId: string, graphInstance: RelationGraphInstance, itemsOnPathClassName: string) => {
clearItemsOnPathActiveStyles(graphInstance, itemsOnPathClassName);
const graphDb = new ShortestPathGraph();
graphDb.loadDataFromRelationGraph(graphInstance);
const nodeIdsOnPath = graphDb.findPath(fromNodeId, toNodeId);
const lineIdsOnPath = getAllLineIdsOnPath(nodeIdsOnPath, graphInstance);
drawMinPath(nodeIdsOnPath, lineIdsOnPath, graphInstance, itemsOnPathClassName);
return { lineIdsOnPath, nodeIdsOnPath };
};
这段表单逻辑展示了输入时如何清除旧选择,并把节点列表变成一个可搜索的端点选择器。
const filtered = data.filter((item) =>
item.text.toLowerCase().includes(keyword.toLowerCase())
);
<input
value={value ? value.text : keyword}
onChange={(e) => {
if (value) {
onChange(null);
}
setKeyword(e.target.value);
setOpen(true);
}}
这个插槽与样式的组合解释了示例的视觉识别特征:头像节点,以及匹配路径上更粗的路线高亮线。
<RGSlotOnNode>
{({ node }: RGNodeSlotProps) => (
<div className="w-12 h-12 flex place-items-center justify-center">
<div className="my-node-avatar" style={{ backgroundImage: `url(${node.data?.icon})` }} />
<div className="my-node-name absolute transform translate-y-[35px]">{node.text}</div>
</div>
)}
</RGSlotOnNode>
.rg-line-peel.my-hightlighted-path {
.rg-line {
stroke-width: 4px;
}
}
这个示例的独特之处
与 search-and-focus 相比,这个示例不止于单节点查找和镜头聚焦,而是把实时图数据转换成一个双端点关系查询。与 line-style-pro 相比,它更强调由人工驱动、带可搜索端点选择的表单工作流,而不是依赖点击触发的路径演示、自动播放或样式实验。与 line-shape-and-label 相比,它不会一次性重写全部连线展示规则,而只是有选择地更新那些对计算路径真正重要的节点和连线。
根据准备好的对比数据,这个示例最强的独特组合在于:基于头像的人物关系图、可拖动的白色查询窗口、由 graphInstance.getNodes() 派生出的选择项、基于实时节点和连线的最短路径计算,以及通过淡化结果路径之外所有内容来实现的焦点加上下文高亮。因此,它比起编辑场景或全局样式控制,更适合作为分析型路径检查的起点。
这一模式还能用在哪里
这一模式很适合迁移到合规与调查工具中,在这些场景下,用户需要解释两个账户、设备或人员在一个已经加载好的图中是如何连接起来的。它也适用于组织分析,例如追踪两名员工之间的汇报路径或影响路径,还适用于基础设施分析,例如在一个已渲染的拓扑图中展示两个服务之间的最短依赖路径。
其中可复用的核心思想是:将可视图本身作为交互的事实来源,从已挂载的实例派生查询选项,并通过运行时更新 API 将路径高亮重新应用到当前节点和连线上。当团队需要图分析能力、但又不想引入一个独立编辑器或第二条渲染管线时,这种做法尤其有用。