美国地图关系图叠加与快照
这个示例在内置美国 SVG 地图上叠加一个小型固定布局关系图。它可从当前节点与连线状态保存实时快照,并在悬浮面板中回放,同时提供共享画布设置与图片导出控制。
带快照回放的美国地图关系图叠加层
这个示例构建了什么
这个示例在内置的美国 SVG 地图上方构建了一个小型的固定位置关系图。界面组合了浅蓝色州形状、橙色圆形节点、橙色连线、内置图工具栏,以及一个可拖动的白色工具窗口。用户可以保存当前图状态、回放已保存的快照、打开设置浮层、切换画布滚轮和拖拽行为,并将图导出为图片。
这里的重点是组合方式,而不是地理分析。地图为手工放置的图提供了视觉背景,而图实例本身仍然是一个普通的 relation-graph 查看器,并在外围配有快照工具。各州路径带有悬停样式,但代码并没有为地图本身绑定州级事件或数据。
数据是如何组织的
初始图数据是在 initializeGraph() 内部创建的一个静态 RGJsonData 对象。它包含 rootId: 'R'、五个带固定 x 和 y 坐标的节点,以及四条带稳定 id 的连线,另外还有两个连线形状覆盖项。在调用 setJsonData() 之前没有预处理步骤:这些坐标已经是最终值,因此图可以在 fixed 布局模式下立即渲染。
地图并不是作为图数据编码的。相反,美国背景位于单独的 MapSvg4US 组件中,该组件会渲染一个包含各州 <path> 元素的大型 SVG。运行时,这个示例还会在 React state 中创建第二种数据结构:一个已保存快照数组,其中每一项都保存一个类似时间戳的 name,以及一个通过 getNodes() 和 getLinks() 从实时图中重建出来的新 RGJsonData 对象。
在真实项目中,同样的结构可以表示楼层平面图上的资产、品牌化区域插画上的服务点、校园地图上的检查点,或工业布局中的设备。可复用的部分,在于将自定义背景组件与一组坐标已知的图数据集分离开来。
relation-graph 是如何使用的
这个示例包裹在 RGProvider 中,这样主图组件和共享的浮动辅助窗口都可以访问当前激活的图上下文。在 MyGraph 内部,RGHooks.useGraphInstance() 驱动整个生命周期:setJsonData() 加载初始数据,moveToCenter() 和 zoomToFit() 对齐视口,getNodes() 和 getLinks() 序列化实时状态,而 clearGraph() 配合 addNodes() 和 addLines() 用于重绘某个已保存快照。
图本身使用 layout.layoutName = 'fixed',因此 relation-graph 会保留显式节点坐标,而不是计算自动布局。选项对象还启用了内置工具栏、使用边框连接点,并将节点填充、边框、宽度、高度以及连线样式的默认值都设置为橙色。这里没有使用自定义节点或连线插槽。主要的视觉定制来自固定数据集,以及在 RelationGraph 内部渲染的 MapSvg4US 子组件。
共享的 DraggableWindow 增加了第二层图集成能力。它的 CanvasSettingsPanel 通过 RGHooks.useGraphStore() 读取实时选项,使用 setOptions() 更新 wheelEventAction 和 dragEventAction,并通过调用 prepareForImageGeneration()、读取 getOptions().backgroundColor、借助 modern-screenshot 捕获图 DOM,然后调用 restoreAfterImageGeneration() 来处理导出。
本地 SCSS 则完成了整体组合。地图路径带有黑色描边、浅蓝填充、指针光标和悬停透明度变化,而快照列表使用蓝色文本、圆角行和悬停背景,让已保存状态更像一个紧凑的控制列表,而不是原始调试输出。
关键交互
核心交互是快照处理。点击保存按钮时,会把当前图序列化为一个新的 RGJsonData 对象,该对象由实时节点和连线状态构建而成,然后插入到快照列表顶部。保存前,示例会将当前快照与最新保存的一条进行比较;如果图没有变化,就显示 The data has not changed,从而避免明显的重复项。
第二个重要交互是回放。浮动面板中的每一条已保存记录都可以点击,点击后会清空当前图并重新绘制存储的节点和连线。围绕这一核心流程,辅助窗口还可以被拖动、最小化,并切换到设置浮层,在那里用户可以修改滚轮行为、修改画布拖拽行为,以及下载当前图像。节点和连线点击处理器只是在控制台打印日志,因此它们并不是这个示例中的主要功能入口。
关键代码片段
下面这段代码展示了该查看器被配置为固定布局叠加层,而不是自动布局示例。
const graphOptions: RGOptions = {
debug: false,
showToolBar: true,
defaultJunctionPoint: RGJunctionPoint.border,
defaultNodeColor: '#f39930',
defaultLineColor: '#f39930',
layout: {
layoutName: 'fixed'
}
};
下面这段代码展示了初始图会在渲染前用显式坐标完成初始化。
const myJsonData: RGJsonData = {
rootId: 'R',
nodes: [
{ id: "R", text: "R", opacity: 1, x: 670, y: 250, nodeShape: RGNodeShape.circle },
{ id: "A", text: "A", opacity: 1, x: 260, y: 160, nodeShape: RGNodeShape.circle },
{ id: "B", text: "B", opacity: 1, x: 530, y: 310, nodeShape: RGNodeShape.circle },
// ... more fixed-position nodes ...
],
下面这段代码说明,快照数据是从实时图实例中重新构建出来的,而不是从原始初始对象复制的。
const allNodesWithPosition = graphInstance.getNodes().map(node => ({
id: node.id,
text: node.text,
x: node.x,
y: node.y,
opacity: node.opacity,
nodeShape: node.nodeShape
}));
下面这段代码展示了如何通过清空图并重新添加存储数据来回放一个已保存快照。
const redrawSnapshot = (theSnapshot: {data: RGJsonData}) => {
graphInstance.clearGraph();
graphInstance.addNodes(theSnapshot.data.nodes);
graphInstance.addLines(theSnapshot.data.lines);
};
下面这段代码展示了自定义背景与图查看器是如何组合在同一个 RelationGraph 树中的。
<RelationGraph
options={graphOptions}
onNodeClick={onNodeClick}
onLineClick={onLineClick}
>
<MapSvg4US />
</RelationGraph>
下面这段代码展示了浮动辅助窗口如何在不重建图数据的情况下,于运行时改变画布行为。
<SettingRow
label="Wheel Event:"
options={[
{ label: 'Scroll', value: 'scroll' },
{ label: 'Zoom', value: 'zoom' },
{ label: 'None', value: 'none' },
]}
value={wheelMode}
onChange={(newValue: string) => { graphInstance.setOptions({ wheelEventAction: newValue }); }}
/>
这个示例的独特之处
根据对比数据,这个示例最有辨识度的部分,在于固定位置图、内置美国 SVG 背景,以及来自当前图实例的实时快照回放这三者的结合。这种组合在库中相对少见,因为它把背景组合与状态捕获和回放放进了同一个查看器外壳中。
它最接近的邻近示例是 map-world,后者使用了几乎相同的快照和浮动面板框架。map-us 的不同之处在于,它把这套框架应用到了一个更密集的美国州地图上,拥有更紧凑的全国背景和更简单的非动画连线。因此,差异主要体现在视觉背景和占用范围上,而不是发明了不同的快照机制。
与 table-relationship 相比,这个示例把重点从表格式节点和 DOM 端点连线,转向自定义图稿叠加以及手工放置坐标的保留。与 use-sigma-layout 和 use-dagre-layout 相比,当位置已知且团队需要轻量级的保存与回放能力,而不是第三方布局计算或布局回写时,它是一个更合适的起点。
这种模式还能用在哪里
这种模式适用于楼层平面图、仓库地图、工厂示意图、校园地图和交通插画等场景,在这些场景中,背景应来自自定义 SVG,而不是图布局引擎。它也适用于需要对手工排布进行轻量级版本保留的评审工具,例如场景对比、事件看板,或会议中希望保留若干命名状态的规划会话。
如果在这个示例之外增加持久化存储,同样的快照格式还可以支持保存预设、审计检查点或可分享的叠加层。这里最可迁移的思路很直接:让背景保持为独立图稿,让 relation-graph 管理节点和连线层,并在当前排布具有意义时序列化实时图。