JavaScript is required

Built-in Line Rendering Options

This example builds a compact center-layout graph that compares several built-in line behaviors, including junction anchors, curve styles, arrow direction, and path-following labels. It loads a small inline RGJsonData dataset, applies fixed circular node defaults, and keeps interaction limited to inspection clicks on nodes and lines.

Comparing Built-In Line Behaviors in One Compact Graph

What This Example Builds

This example builds a small full-height relation-graph canvas that acts as a visual reference for line rendering options. The graph uses a center layout, circular nodes, and color-coded connections so the viewer can compare orthogonal routing, curved branches, arrow direction, and label placement in one prepared scene.

Users can click nodes or lines, but those handlers only log the selected objects to the console. The main point of the example is not editing or runtime controls. Its value is that the line variations are encoded directly in the loaded graph data, so the canvas reads like a focused comparison board for built-in edge behavior.

How the Data Is Organized

The data is declared inline inside initializeGraph() as one RGJsonData object with rootId: 'a', 12 nodes, and 12 lines. There is no preprocessing step before setJsonData(): the example constructs the final dataset in code and loads it directly.

The important structure is in the lines array rather than the nodes array. Each edge record carries its own rendering metadata, including lineShape, fromJunctionPoint, toJunctionPoint, showStartArrow, showEndArrow, color, and useTextOnPath. That makes the dataset easy to map to real business cases where each connection has its own visual meaning, such as workflow branches, dependency directions, integration routes, or data lineage annotations.

How relation-graph Is Used

index.tsx wraps the example in RGProvider, and MyGraph.tsx retrieves the active graph instance with RGHooks.useGraphInstance(). The component then configures the graph with a center layout, fixed circular node defaults, and custom level gaps.

The actual graph load happens once in useEffect(). initializeGraph() calls setJsonData() and then immediately repositions the viewport with moveToCenter() and zoomToFit(), so the prepared comparison scene is visible without any user setup.

This example does not use node slots, line slots, canvas slots, or editing APIs. It relies on the default renderer and shows how far built-in edge options can go without custom SVG or overlay UI. The visible styling is mostly driven by graph options and per-line colors in the data. A local SCSS file is imported, but the reviewed JSX does not mount the .my-graph wrapper defined there, so CSS overrides are not a confirmed part of the rendered result.

Key Interactions

The only custom interactions are inspection clicks. Clicking a node logs the RGNode object, and clicking a line logs both the RGLine and the related RGLink. Those handlers help developers inspect what relation-graph returns for selected items, but they do not mutate the graph, open menus, or switch modes.

The rest of the experience is visual comparison rather than active manipulation. The example prepares all line variants up front and uses automatic centering and fit-to-view on mount so the viewer can study the differences immediately.

Key Code Fragments

This fragment shows that the example uses standard graph options rather than a custom renderer to shape the overall scene.

const graphOptions: RGOptions = {
    checkedItemBackgroundColor: '#666666',
    defaultNodeShape: RGNodeShape.circle,
    defaultNodeWidth: 60,
    defaultNodeHeight: 60,
    defaultNodeBorderWidth: 1,
    layout: {
        layoutName: 'center',
        levelGaps: [200, 300]
    }
};

This fragment shows that the graph is loaded once from inline RGJsonData and then positioned for viewing.

useEffect(() => {
    initializeGraph();
}, []);

// ...

await graphInstance.setJsonData(myJsonData);
graphInstance.moveToCenter();
graphInstance.zoomToFit();

This fragment shows how orthogonal routing and junction anchors are varied per line record.

{ from: 'a', to: 'c', text: 'Bottom -> Left', lineShape: RGLineShape.StandardOrthogonal, fromJunctionPoint: RGJunctionPoint.bottom, toJunctionPoint: RGJunctionPoint.left },
{ from: 'a', to: 'b', text: 'LR -> LR', lineShape: RGLineShape.StandardOrthogonal, fromJunctionPoint: RGJunctionPoint.lr, toJunctionPoint: RGJunctionPoint.lr },
{ from: 'a', to: 'e', text: 'Top -> Right', lineShape: RGLineShape.StandardOrthogonal, fromJunctionPoint: RGJunctionPoint.top, toJunctionPoint: RGJunctionPoint.right },
{ from: 'a', to: 'i', text: 'LR -> LR', lineShape: RGLineShape.StandardOrthogonal, fromJunctionPoint: RGJunctionPoint.lr, toJunctionPoint: RGJunctionPoint.lr },

This fragment shows the paired arrow-direction comparison on duplicated endpoints.

{ from: 'i', to: 'm', text: 'Data: i > m, But Displayed as m > i', showStartArrow: true, showEndArrow: false, color: '#00ced1' },
{ from: 'i', to: 'm', text: 'Data:i > m', showStartArrow: false, showEndArrow: true, color: 'rgba(255, 140, 0, 1)' },

This fragment shows the difference between a normal Curve5 label and a path-following label.

{ from: 'e', to: 'p3', text: 'The text does not follow along this line.', lineShape: RGLineShape.Curve5, color: '#ffd700' },
{ from: 'e', to: 'p4', text: 'The text can follow along this line.', useTextOnPath: true, lineShape: RGLineShape.Curve5, color: '#ffd700' }

What Makes This Example Distinct

Compared with nearby examples, this one is notable for how much it demonstrates with very little scaffolding. The comparison data shows that its distinguishing pattern is a minimal viewer built around one small center-layout graph where most of the lesson comes from per-line metadata inside RGJsonData, not from slots, custom SVG markers, utility panels, or editing tools.

Against line, the difference is compactness rather than breadth. line covers a wider line-configuration surface with more UI and more rendering variations, while this example removes that extra surface area so the built-in fields are easier to study in isolation. Against bothway-tree-faq, it is not focused on one arrow-direction question; it combines arrow direction, junction routing, and Curve5 label behavior in one prepared canvas. Against examples such as show-single-nodes and node-menu-2, its reusable value is edge presentation controlled by data fields alone, not preprocessing tricks or slot-based overlays.

The most distinctive detail is the use of paired micro-comparisons on nearly duplicated connections. Two i -> m lines contrast start-arrow and end-arrow display, and two e -> p* lines contrast ordinary labels with useTextOnPath. That makes the example especially useful as a quick reference when a team wants to confirm which built-in flags affect line presentation without first moving into custom rendering.

Where Else This Pattern Applies

This pattern transfers well to diagrams where the meaning of a connection matters as much as the meaning of a node. Examples include approval flows with different branch semantics, service dependency maps with upstream or downstream emphasis, data lineage graphs that need distinct visual treatment for transport versus derivation, and network diagrams where anchor choice helps explain route direction.

It also works as a documentation and QA pattern. A team can build a small comparison graph like this to validate how built-in line options behave before committing to custom slots, custom markers, or a larger graph editor. In training material, the same structure can serve as a compact reference board for developers who need to learn which line metadata fields change routing, arrows, and text behavior.