JavaScript is required

Center Layout Style Controls

This example demonstrates relation-graph's built-in center layout on one fixed radial network and layers a floating control window above it. Users can switch node shape, line shape, and line-label placement on the live graph, while the shared overlay also exposes canvas interaction settings and image export.

Live Style Switching on a Center Layout Graph

What This Example Builds

This example builds a full-viewport relation graph that uses the built-in center layout and places a floating white control window above the canvas. The graph itself is a fixed radial network with one root node in the middle, orange nodes, and labeled relationship lines.

Users can switch node shape, line shape, and whether line labels follow the line path, all on the live graph that is already on screen. The same floating window can also be dragged, minimized, opened into a canvas-settings panel, and used to export the current graph view as an image.

The main point is that the graph structure does not change. The example is a compact reference for changing graph presentation in place on top of one centered layout.

How the Data Is Organized

The data is declared inline as one RGJsonData object with rootId: '2', a nodes array, and a lines array. The node IDs and labels are generic placeholders such as Node-2, while the line labels use a small set of relationship texts such as Investment and Executive.

There is no preprocessing step that rewrites the dataset before setJsonData() runs. Initialization applies graph options first, then loads the static JSON once. After that, the runtime controls only restyle the existing nodes and lines through instance APIs instead of rebuilding the data.

In real projects, the same data shape could represent a company-centric ownership map, a stakeholder network around one focal person, a system dependency hub, or any small relationship graph where one central entity needs to stay visually dominant.

How relation-graph Is Used

The page is wrapped in RGProvider, and the graph logic reads the active instance with RGHooks.useGraphInstance(). The floating settings overlay in the shared DraggableWindow also reads the current instance, and it uses RGHooks.useGraphStore() to reflect the current wheel and drag modes.

The graph is initialized through the instance API rather than through the RelationGraph options prop. The component calls setOptions(graphOptions), then setJsonData(myJsonData), then recenters the viewport with moveToCenter() and zoomToFit(). Those initial options enable layoutName: 'center', set orange no-border nodes, and start with straight lines that connect at the node border.

The live styling behavior is handled by React state plus batch updates on the current graph elements. When nodeShape, lineShape, or textOnPath changes, the component iterates over getNodes() and getLines() and applies updateNode() or updateLine() to each element. Circular nodes are forced to 70x70, while rectangular nodes switch back to auto sizing with width: 0 and height: 0. Straight lines keep border junction points, while orthogonal and curved lines switch to RGJunctionPoint.ltrb.

This example does not use node slots, line slots, custom renderers, or editing APIs. The local stylesheet mainly refines built-in checked states: node text stays white, and checked lines and labels reuse the same orange accent as the node palette.

Key Interactions

The three SimpleUISelect controls are the main interaction surface. One switches between rectangular and circular nodes, one switches between straight, orthogonal, and curved lines, and one toggles line labels between normal placement and text-on-path mode.

The floating description window is draggable and minimizable, so the controls can be moved out of the way without leaving the page. Its settings view exposes two more workspace-level controls: wheel behavior can switch between scroll, zoom, and none, and canvas dragging can switch between selection, move, and none.

The settings panel also supports image export. It asks relation-graph to prepare the canvas for image generation, renders the DOM into a blob with modern-screenshot, downloads the file, and then restores the graph state.

Key Code Fragments

This fragment shows that the demo starts from the built-in center layout and sets the initial visual defaults in code before any data is loaded.

const graphOptions: RGOptions = {
  debug: true,
  defaultNodeBorderWidth: 0,
  defaultNodeColor: 'rgba(238, 178, 94, 1)',
  defaultLineShape: RGLineShape.StandardStraight,
  layout: {
    layoutName: 'center'
  },
  defaultJunctionPoint: RGJunctionPoint.border
};

This fragment shows that the graph payload is one inline dataset with an explicit root node, so the layout always has a stable center.

const myJsonData: RGJsonData = {
  rootId: '2',
  nodes: [
    { id: '1', text: 'Node-1' },
    { id: '2', text: 'Node-2' },
    { id: '3', text: 'Node-3' },
    { id: '4', text: 'Node-4' },
    { id: '6', text: 'Node-6' }
  ],
  // ...
};

This fragment proves that initialization applies options first, then loads the dataset, then normalizes the viewport around the result.

const initializeGraph = async () => {
  graphInstance.setOptions(graphOptions);
  await graphInstance.setJsonData(myJsonData);
  graphInstance.moveToCenter();
  graphInstance.zoomToFit();
};

This fragment shows the core runtime pattern: update the current nodes in place instead of rebuilding RGJsonData when the presentation mode changes.

graphInstance.getNodes().forEach((node) => {
  if (nodeShape === RGNodeShape.circle) {
    graphInstance.updateNode(node, {
      nodeShape,
      width: 70,
      height: 70
    });
  } else {
    graphInstance.updateNode(node, {
      nodeShape,
      width: 0,
      height: 0
    });
  }
});

This fragment shows the matching line update flow, including the global text-on-path toggle and the junction-point change for non-straight lines.

graphInstance.getLines().forEach((line) => {
  if (lineShape === RGLineShape.StandardStraight) {
    graphInstance.updateLine(line, {
      lineShape,
      fromJunctionPoint: RGJunctionPoint.border,
      toJunctionPoint: RGJunctionPoint.border,
      useTextOnPath: textOnPath
    });
  } else {
    graphInstance.updateLine(line, {
      lineShape,
      fromJunctionPoint: RGJunctionPoint.ltrb,
      toJunctionPoint: RGJunctionPoint.ltrb,
      useTextOnPath: textOnPath
    });
  }
});

This fragment shows that the floating overlay is a real graph utility surface, not just a description box, because it directly changes canvas behavior and drives image export.

<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 nearby center layout examples, this one is more about presentation switching than about layout spacing or layout math. The comparison record explicitly separates it from center-layout-options: both use the same floating-window pattern and the same built-in layout family, but layout-center spends its runtime logic on node shape, line shape, junction behavior, and line-label placement instead of distanceCoefficient or levelGaps.

Compared with line, this example behaves like a compact whole-graph switcher rather than a broad line-style gallery. It changes every visible node and edge together through a few selectors, instead of encoding many edge variants directly into the dataset, CSS classes, or marker definitions.

Compared with deep-each and layout-diy, the interaction is lighter and more presentation-oriented. It does not isolate subtrees or compute custom coordinates. It keeps the built-in center layout as a stable radial canvas and uses batch updateNode() and updateLine() calls to compare rendering modes on one already-loaded graph.

That combination is the main reason this example stands out: a centered radial composition, orange no-border nodes, a floating white overlay, and three live selectors that restyle the existing graph without replacing the dataset.

Where Else This Pattern Applies

This pattern transfers well to graph workbenches where teams need to compare presentation options on one representative relationship dataset before settling on final defaults. Examples include customer relationship maps, investor or ownership overviews, service dependency hubs, and stakeholder diagrams centered on one main entity.

It is also useful for documentation or design-review tooling. Keeping one graph structure fixed while switching node geometry, line routing, and label placement makes it easier to evaluate readability tradeoffs without mixing style experiments with layout changes or data reloads.