Export Full Graph Image
This example shows how to export the full relation-graph scene as a downloadable image from custom UI controls. It loads a static left-to-right tree, prepares the graph for capture, converts the prepared DOM into a blob with modern-screenshot, and restores graph state after the download flow completes.
Export the Full Relation Graph as a Downloadable Image
What This Example Builds
This example builds a read-only relation-graph viewer whose main job is exporting the whole graph as an image file. The page shows a left-to-right tree with white rectangular nodes, curved labelled links, a floating description window, and a custom image button in a bottom mini toolbar.
Users can trigger the same export flow from two places: the floating panel and the graph-attached mini toolbar. The important result is that export does not depend on the current zoom level or the visible viewport, because the graph is prepared specifically for image generation before capture.
How the Data Is Organized
The graph data is an inline RGJsonData object declared inside initializeGraph(). It contains a rootId, a flat nodes array, and a flat lines array where each line already has its own explicit id.
There is no heavy preprocessing step before setJsonData(). The only preparation is defining the dataset in code, loading it into the instance, then centering and fitting the graph. In a real application, the same shape could represent product structures, manufacturing systems, subsystem breakdowns, dependency trees, or any hierarchy that needs a report-ready snapshot.
How relation-graph Is Used
The example uses relation-graph as a tree viewer with explicit layout and export lifecycle control. The graph is configured with layoutName: 'tree', from: 'left', and fixed levelGaps, so the result is a wide technical tree rather than a force-directed diagram.
Graph options define most of the visual language: rectangular white nodes, curved lines, left-right junctions, line text rendered on the path, and showToolBar: false so the default toolbar does not compete with the custom export controls. After the data loads, the code calls moveToCenter() and zoomToFit() to make the scene presentation-ready immediately.
The example also uses relation-graph slots and hooks directly. RGHooks.useGraphInstance() gives access to setJsonData(), moveToCenter(), zoomToFit(), prepareForImageGeneration(), and restoreAfterImageGeneration(). RGSlotOnView plus RGMiniToolBar injects a custom export button into the viewport layer, which keeps the action attached to the graph even though the built-in toolbar is disabled.
The floating helper window comes from a shared local component. In this example it is not just explanatory chrome: it adds a second export entry point, exposes a settings overlay, and uses graphInstance.setOptions() to change wheelEventAction and dragEventAction at runtime.
Key Interactions
The primary interaction is image export. Clicking either Download Image in the floating panel or the red image icon in the bottom mini toolbar runs the same capture workflow.
The floating window itself is interactive. It can be dragged, minimized, and switched into a settings overlay. That overlay changes wheel behavior between scroll, zoom, and none, and changes canvas drag behavior between selection, move, and none before running another export action if needed.
The graph data is loaded automatically on mount, then centered and fit to the viewport. That means users do not need to manually pan or zoom before generating a full-scene image.
Key Code Fragments
This fragment shows that the example is intentionally configured as a left-to-right tree with restrained styling and no built-in toolbar.
const graphOptions: RGOptions = {
reLayoutWhenExpandedOrCollapsed: true,
defaultExpandHolderPosition: 'right',
defaultNodeShape: RGNodeShape.rect,
defaultNodeBorderWidth: 1,
defaultNodeColor: '#fff',
defaultLineShape: RGLineShape.Curve2,
defaultJunctionPoint: RGJunctionPoint.lr,
defaultLineTextOnPath: true,
layout: { layoutName: 'tree', from: 'left', levelGaps: [400, 400, 400, 400] },
showToolBar: false
};
This fragment proves that the graph content is seeded as inline RGJsonData and loaded programmatically before the viewport is aligned.
const myJsonData: RGJsonData = {
rootId: '2',
nodes: [
{ id: '2', text: 'ALTXX' }, { id: '3', text: 'CH2 TTN' }, { id: '4', text: 'CH1 AlCu' },
// ...
],
lines: [
{ id: 'l1', from: '2', to: '5', text: 'Subsystem' },
// ...
]
};
await graphInstance.setJsonData(myJsonData);
graphInstance.moveToCenter();
graphInstance.zoomToFit();
This fragment is the core export pipeline: relation-graph prepares the scene, modern-screenshot turns the DOM into a blob, and the graph state is restored afterward.
const downloadImage = async () => {
const canvasDom = await graphInstance.prepareForImageGeneration();
const imageBlob = await domToImageByModernScreenshot(canvasDom, {
backgroundColor: '#ffffff'
});
if (imageBlob) {
downloadBlob(imageBlob, 'my-image-name');
}
await graphInstance.restoreAfterImageGeneration();
};
This fragment shows how the example adds a graph-attached export control through the view slot instead of relying on the default toolbar.
<RelationGraph options={graphOptions}>
<RGSlotOnView>
<RGMiniToolBar positionV='bottom' direction='v'>
<div
className="w-8 h-8 border rounded flex place-items-center justify-center bg-red-700 animate-pulse text-white cursor-pointer hover:text-yellow-200 hover:animate-none"
onClick={downloadImage}
>
<ImageIcon size={20} />
</div>
</RGMiniToolBar>
</RGSlotOnView>
</RelationGraph>
This fragment shows that the shared helper is part of the example’s actual behavior, because it changes runtime canvas interaction modes through the graph instance.
<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
Compared with the other generate-image-* examples, this one is more delivery-oriented than preview-oriented. The captured result is downloaded immediately as a blob instead of being held in component state as Base64 text or an inline preview.
Its strongest differentiator is the export surface. The built-in toolbar is disabled, but the example still places a custom export action directly inside the graph viewport by combining RGSlotOnView with a bottom RGMiniToolBar. The comparison data marks that graph-integrated export affordance as one of the rarest traits in this export cluster.
It is also more focused on clean report output than decorative capture variants. The comparison records show that neighboring examples emphasize watermarking, patterned backgrounds, or viewport-only screenshots, while this example keeps a neutral white background and prepares the full graph so users do not have to manage zoom, panning, toolbar visibility, or minimap state before exporting.
Where Else This Pattern Applies
This pattern transfers well to product structure exports, manufacturing or supply-chain breakdowns, system architecture trees, dependency maps, and compliance documentation where teams need a consistent full-graph image rather than an interactive screen capture.
It is also a good starting point for share and reporting workflows: scheduled snapshot generation, one-click export from a custom graph toolbar, download actions in internal admin tools, or branded export variants that keep the same prepareForImageGeneration() and restore lifecycle but swap the screenshot options, filename strategy, or surrounding UI.