JavaScript is required

Adjustable Graph Minimap

This example shows how to mount `RGMiniView` as a graph-overlay minimap on a large force-layout viewer and control its corner placement, width, and height at runtime. A shared floating helper window adds canvas mode switching and image export, while randomized node sizes, shapes, and colors make the overview visually informative.

Adjustable Minimap Overlay for a Large Force-Layout Graph

What This Example Builds

This example builds a full-screen force-layout graph viewer with an always-visible minimap overlay. The canvas is intentionally busy: more than one hundred nodes are scattered across a dark dotted background, node sizes and shapes vary, and the minimap stays on top of the graph so users can keep track of the overall structure while navigating.

Users can move the minimap to any corner, resize it with separate width and height sliders, drag or minimize the floating helper window, open a shared settings overlay for canvas wheel and drag behavior, and download the current graph as an image. The main teaching point is that RGMiniView is not treated as passive scaffolding. It is mounted as an overlay widget and controlled directly by React state.

How the Data Is Organized

The data is declared inline inside initializeGraph() as one RGJsonData object with rootId: 'a', 103 nodes, and 102 lines. Structurally it is a large branching hierarchy, but the node labels are generic identifiers such as b4-7 and e2-9, so the dataset is serving as a navigation surface rather than as domain content.

There is important preprocessing before setJsonData(...). Every node is mutated with a random color, a random width, a random height, and either RGNodeShape.circle or RGNodeShape.rect. That preprocessing makes the minimap more informative because the overview has varied footprints instead of identical boxes. After the initial load, the example does not rebuild the dataset. The later UI controls only change widget state and canvas behavior. In real work, the same structure could stand in for a topology map, an organization tree, a dependency graph, or a knowledge graph where orientation on a large canvas matters more than editing.

How relation-graph Is Used

index.tsx wraps the page with RGProvider, and MyGraph.tsx uses RGHooks.useGraphInstance() as the main control surface. On mount, the example calls setJsonData(...), moveToCenter(), and zoomToFit() once. The graph options are deliberately narrow: showToolBar: false, defaultLineColor: '#666', and a force layout with maxLayoutTimes: Number.MAX_SAFE_INTEGER.

The key relation-graph extension point is RGSlotOnView. Instead of customizing node bodies or line rendering, the example mounts RGMiniView into the graph’s overlay layer and binds its position, width, and height props to local React state. That makes the minimap part of the viewer chrome rather than part of node content. The example does not implement graph editing, node authoring, or a custom layouter. It keeps the graph itself close to default rendering and puts the customization budget into navigation utilities.

The shared DraggableWindow component contributes the floating description and control surface. Inside its settings overlay, CanvasSettingsPanel uses RGHooks.useGraphStore() to read the live dragEventAction and wheelEventAction, then calls graphInstance.setOptions(...) to update those values at runtime. The same panel supports export through prepareForImageGeneration(), getOptions(), domToImageByModernScreenshot(...), and restoreAfterImageGeneration().

The stylesheet finishes the viewer treatment. It uses relation-graph canvas CSS variables such as --rg-canvas-scale and the canvas offsets to keep a dotted background aligned with pan and zoom, enlarges node labels to white text, and changes checked line labels to a filled color chip. Those are local style overrides, not guide-level assumptions.

Key Interactions

  • Clicking the corner selector moves the minimap between top-left, top-right, bottom-left, and bottom-right without reloading graph data.
  • Moving the width slider changes the minimap width immediately.
  • Moving the height slider changes the minimap height immediately.
  • Dragging the floating helper window repositions the control surface so it does not have to cover a fixed part of the graph.
  • Minimizing the helper window collapses the descriptive panel while keeping the graph visible.
  • Opening the settings overlay exposes shared runtime controls for wheel behavior, canvas drag behavior, and image export.
  • The local explanatory text tells users they can drag the minimap’s visible-area indicator to move the viewport; the reviewed source relies on RGMiniView itself for that behavior rather than implementing custom drag handlers.

Key Code Fragments

This fragment shows that the example treats minimap state as first-class React state alongside the graph instance:

const graphInstance = RGHooks.useGraphInstance();
const [miniViewPosition, setMiniViewPosition] = React.useState('br');
const [miniViewSize, setMiniViewSize] = React.useState<{width: number, height: number}>({width: 300, height: 150});
useEffect(() => {
    initializeGraph();
}, []);

This fragment proves that the sample data is preprocessed before loading so the overview has varied colors, sizes, and shapes:

const randomColorRange = ['#5b05f1', '#FD8B37', '#9b9903', '#247c02'];
myJsonData.nodes.forEach(node => {
    node.color = randomColorRange[Math.floor(Math.random() * randomColorRange.length)];
    node.width = 30 + Math.floor(Math.random() * 200);
    node.height = 30 + Math.floor(Math.random() * 200);
    node.nodeShape = Math.random() < 0.3 ? RGNodeShape.circle : RGNodeShape.rect;
});
await graphInstance.setJsonData(myJsonData);

This fragment shows that the graph configuration hides the built-in toolbar and keeps the layout configuration focused on a large force-driven viewer:

const graphOptions: RGOptions = {
    showToolBar: false,
    defaultLineColor: '#666',
    layout: {
        layoutName: 'force',
        maxLayoutTimes: Number.MAX_SAFE_INTEGER
    }
};

This fragment shows how the corner selector turns minimap placement into a runtime control instead of a hard-coded choice:

<SimpleUISelect
    data={[
        { value: 'tl', text: 'Top-Left' },
        { value: 'tr', text: 'Top-Right' },
        { value: 'bl', text: 'Bottom-Left' },
        { value: 'br', text: 'Bottom-Right' }
    ]}
    currentValue={miniViewPosition}
    onChange={(newValue: string) => { setMiniViewPosition(newValue); }}
/>

This fragment shows the state-driven widget pattern: slider values are fed straight into the RGMiniView overlay props:

<SimpleUISlider currentValue={miniViewSize.width} min={50} max={500} step={10} onChange={(newValue) => {setMiniViewSize({...miniViewSize, width: newValue});}} />
<SimpleUISlider currentValue={miniViewSize.height} min={50} max={500} step={10} onChange={(newValue) => {setMiniViewSize({...miniViewSize, height: newValue});}} />
<RelationGraph options={graphOptions}>
    <RGSlotOnView>
        <RGMiniView width={`${miniViewSize.width}px`} height={`${miniViewSize.height}px`} position={miniViewPosition as RGWidgetPosition} />
    </RGSlotOnView>
</RelationGraph>

This fragment shows that the floating settings overlay stays synchronized with the live graph options and updates canvas behavior through setOptions(...):

const { options } = RGHooks.useGraphStore();
const dragMode = options.dragEventAction;
const wheelMode = options.wheelEventAction;

<SettingRow
    label="Wheel Event:"
    value={wheelMode}
    onChange={(newValue: string) => { graphInstance.setOptions({ wheelEventAction: newValue }); }}
/>

This fragment shows the export flow that prepares the graph for capture, renders the canvas DOM into an image blob, and restores the graph state:

const canvasDom = await graphInstance.prepareForImageGeneration();
let graphBackgroundColor = graphInstance.getOptions().backgroundColor;
if (!graphBackgroundColor || graphBackgroundColor === 'transparent') {
    graphBackgroundColor = '#ffffff';
}
const imageBlob = await domToImageByModernScreenshot(canvasDom, {
    backgroundColor: graphBackgroundColor
});
await graphInstance.restoreAfterImageGeneration();

This fragment shows how the stylesheet makes the background follow the graph viewport instead of behaving like a static page texture:

.relation-graph {
    --rg-canvas-scale: 1;
    --rg-canvas-offset-x: 0px;
    --rg-canvas-offset-y: 0px;
    background-position: var(--rg-canvas-offset-x) var(--rg-canvas-offset-y);
    background-size: calc(var(--rg-canvas-scale) * 15px) calc(var(--rg-canvas-scale) * 15px);
    background-image: radial-gradient(circle, rgb(197, 197, 197) calc(var(--rg-canvas-scale) * 1px), transparent 0);
}

What Makes This Example Distinct

The prepared comparison data makes the distinction clear. The closest minimap-oriented neighbor is node, but there the mini view is secondary to a broader node-style showcase. In gee-thumbnail-diagram, the overview widget is the primary lesson: corner placement, width, and height are all exposed as live controls, and the rest of the graph stays comparatively close to default rendering.

The comparison file also separates this example from drag-and-wheel-event and node-style3. Those examples share the floating helper shell and some of the same runtime canvas utilities, but their main lessons are different. Here the important local pattern is an RGSlotOnView-mounted RGMiniView on top of a large, visually busy force graph. The hidden toolbar, randomized node footprint preprocessing, dark dotted canvas, and movable helper panel together make this a stronger starting point for navigation-heavy graph viewers than for force tuning, node skinning, or general interaction testing.

Where Else This Pattern Applies

This pattern transfers well to graph screens where users need orientation on a large canvas without entering a full editor workflow. Examples include service dependency maps, infrastructure topology views, large organization hierarchies, knowledge maps, and investigation workspaces where the main problem is staying aware of overall position while zooming into detail.

It also applies when teams want auxiliary viewer tools to be configurable at runtime. The same structure can support operator-specific minimap presets, resizable overview widgets for different screen sizes, exportable audit views, and floating utility panels that expose pan or zoom behavior without changing the underlying graph data model.