JavaScript is required

US Map Graph Overlay and Snapshots

This example overlays a small fixed-layout relation graph on a bundled SVG map of the United States. It saves live graph snapshots from the current node and link state, replays them from a floating panel, and exposes shared canvas settings and image export controls.

US Map Graph Overlay with Snapshot Replay

What This Example Builds

This example builds a small fixed-position relation graph on top of a bundled SVG map of the United States. The screen combines pale-blue state shapes, orange circular nodes, orange connectors, the built-in graph toolbar, and a draggable white utility window. Users can save the current graph state, replay saved snapshots, open a settings overlay, switch canvas wheel and drag behavior, and export the graph as an image.

The important point is the composition pattern, not geographic analytics. The map provides visual context for a hand-placed graph, while the graph instance remains a normal relation-graph viewer with snapshot utilities around it. The state paths have hover styling, but the code does not attach state-level events or data binding to the map itself.

How the Data Is Organized

The initial graph data is a static RGJsonData object created inside initializeGraph(). It contains rootId: 'R', five nodes with fixed x and y coordinates, and four lines with stable ids plus two line-shape overrides. There is no preprocessing step before setJsonData(): the coordinates are already final, so the graph can be rendered immediately in fixed layout mode.

The map is not encoded as graph data. Instead, the U.S. backdrop lives in a separate MapSvg4US component that renders a large SVG full of state <path> elements. At runtime the example creates a second data shape: an array of saved snapshots in React state, where each item stores a timestamp-like name and a new RGJsonData object rebuilt from the live graph through getNodes() and getLinks().

In real projects, the same structure can represent assets placed on a floor plan, service locations on a branded regional illustration, checkpoints on a campus map, or devices on an industrial layout. The reusable part is the separation between a custom backdrop component and a graph dataset whose coordinates are already known.

How relation-graph Is Used

The example is wrapped in RGProvider, which lets both the main graph component and the shared floating helper window access the active graph context. Inside MyGraph, RGHooks.useGraphInstance() drives the whole lifecycle: setJsonData() loads the seed data, moveToCenter() and zoomToFit() align the viewport, getNodes() and getLinks() serialize the live state, and clearGraph() with addNodes() and addLines() redraw a saved snapshot.

The graph itself uses layout.layoutName = 'fixed', so relation-graph preserves the explicit node coordinates instead of computing a layout. The options object also enables the built-in toolbar, uses border junction points, and sets orange defaults for node fill, border, width, height, and line styling. No custom node or line slots are used here. The main visual customization comes from the fixed dataset plus the MapSvg4US child rendered inside RelationGraph.

The shared DraggableWindow adds a second layer of graph integration. Its CanvasSettingsPanel reads live options through RGHooks.useGraphStore(), updates wheelEventAction and dragEventAction with setOptions(), and handles export by calling prepareForImageGeneration(), reading getOptions().backgroundColor, capturing the graph DOM with the modern-screenshot helper, and then calling restoreAfterImageGeneration().

Local SCSS finishes the composition. The map paths get black strokes, light-blue fills, a pointer cursor, and hover opacity changes, while the snapshot list uses blue text, rounded rows, and a hover background so saved states behave like a compact control list rather than raw debug output.

Key Interactions

The main interaction is snapshot handling. Clicking the save button serializes the current graph into a new RGJsonData object built from the live node and link state, then prepends it to the snapshot list. Before saving, the example compares the current snapshot with the newest saved one and shows The data has not changed if the graph is unchanged, which prevents obvious duplicates.

The second important interaction is replay. Each saved row in the floating panel is clickable, and clicking it clears the current graph and redraws the stored nodes and lines. Around that core flow, the helper window can be dragged, minimized, and switched into a settings overlay where users can change wheel behavior, change canvas drag behavior, and download an image of the current graph. The node and line click handlers only log to the console, so they are not a meaningful feature entry point in this example.

Key Code Fragments

This fragment shows that the viewer is configured as a fixed-layout overlay rather than an automatic layout demo.

const graphOptions: RGOptions = {
  debug: false,
  showToolBar: true,
  defaultJunctionPoint: RGJunctionPoint.border,
  defaultNodeColor: '#f39930',
  defaultLineColor: '#f39930',
  layout: {
    layoutName: 'fixed'
  }
};

This fragment shows that the initial graph is seeded with explicit coordinates before anything is rendered.

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 ...
  ],

This fragment proves that snapshot data is rebuilt from the live graph instance, not copied from the original seed object.

const allNodesWithPosition = graphInstance.getNodes().map(node => ({
    id: node.id,
    text: node.text,
    x: node.x,
    y: node.y,
    opacity: node.opacity,
    nodeShape: node.nodeShape
}));

This fragment shows how a saved snapshot is replayed by clearing the graph and re-adding stored data.

const redrawSnapshot = (theSnapshot: {data: RGJsonData}) => {
  graphInstance.clearGraph();
  graphInstance.addNodes(theSnapshot.data.nodes);
  graphInstance.addLines(theSnapshot.data.lines);
};

This fragment shows that the custom backdrop and the graph viewer are composed in the same RelationGraph tree.

<RelationGraph
  options={graphOptions}
  onNodeClick={onNodeClick}
  onLineClick={onLineClick}
>
  <MapSvg4US />
</RelationGraph>

This fragment shows that the floating helper window can change canvas behavior at runtime without rebuilding graph data.

<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 }); }}
/>

What Makes This Example Distinct

According to the comparison data, the most distinctive part of this example is the combination of a fixed-position graph, a bundled U.S. SVG backdrop, and live snapshot replay from the current graph instance. That combination is relatively rare in the library because it joins backdrop composition with state capture and replay in the same viewer shell.

Its closest neighbor is map-world, which uses almost the same snapshot and floating-panel scaffold. map-us is distinct because it applies that scaffold to a denser U.S. state map with a tighter national backdrop and simpler non-animated links. So the difference is mostly about the visual context and footprint, not about inventing a different snapshot mechanism.

Compared with table-relationship, this example shifts the lesson away from table-style nodes and DOM endpoint wiring toward custom-artwork overlay and preservation of hand-placed positions. Compared with use-sigma-layout and use-dagre-layout, it is a better starting point when positions are already known and the team needs lightweight save-and-replay behavior, not third-party layout computation or layout writeback.

Where Else This Pattern Applies

This pattern fits floor plans, warehouse maps, plant diagrams, campus maps, and transportation illustrations where the background should come from a custom SVG rather than from a graph layout engine. It is also useful for review tools that need lightweight versioning of manual arrangements, such as scenario comparison, incident boards, or planning sessions where users want to preserve a few named states during a meeting.

If persistent storage is added outside this demo, the same snapshot format can support saved presets, audit checkpoints, or shareable overlays. The main transferable idea is straightforward: keep the backdrop as independent artwork, let relation-graph manage the node-link layer, and serialize the live graph when the current arrangement matters.