Radial Tree Layout in React Diagram Component

21 Oct 202524 minutes to read

A radial tree layout is a specialized diagram that presents hierarchical information with a central node at the core, surrounded by branches extending outward in a circular, tree-like structure. This layout is particularly effective for visualizing organizational charts, family trees, mind maps, and network relationships where understanding the relationship distance from a central concept is important.

The central node represents the main concept or topic, with child nodes arranged in concentric circles based on their hierarchical level. The layout rootproperty can be used to define the root node of the layout. When no root node is specified, the algorithm automatically identifies the node without any incoming edges (InEdges connector count of 0) as the root node. To create a radial tree, set the type of the layout to RadialTree.

The RadialTree layout provides comprehensive support for controlling node spacing and arrangement. The HorizontalSpacingand VerticalSpacing properties allow precise control over the space between nodes, measured in pixels. The arrangement creates an expanding concentric pattern where radial proximity to the root node indicates the hierarchical level.

Radial Tree with DataSource

Creating a radial tree layout with a data source provides automatic node generation and connection management. This approach is ideal when working with structured data objects that define hierarchical relationships.

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, Inject, DataBinding, RadialTree } from "@syncfusion/ej2-react-diagrams";
import { DataManager, Query } from "@syncfusion/ej2-data";

//Initializes data source
let data = [
    {
        Id: 'parent',
        Name: 'Maria Anders',
        Designation: 'Managing Director'
    },
    {
        Id: '1',
        Name: 'Ana Trujillo',
        Designation: 'Project Manager',
        ReportingPerson: 'parent',
    },
    {
        Id: '2',
        Name: 'Lino Rodri',
        Designation: 'Project Manager',
        ReportingPerson: 'parent',
    },
    {
        Id: '3',
        Name: 'Philip Cramer',
        Designation: 'Project Manager',
        ReportingPerson: 'parent',
    },
    {
        Id: '4',
        Name: 'Pedro Afonso',
        Designation: 'Project Manager',
        ReportingPerson: 'parent',
    },
    {
        Id: '15',
        Name: 'Paul Henriot',
        Designation: 'Project Manager',
        ReportingPerson: 'parent',
    },
    {
        Id: '18',
        Name: 'Laura Callahan',
        Designation: 'Project Manager',
        ReportingPerson: 'parent',
    },
    {
        Id: '5',
        Name: 'Anto Moreno',
        Designation: 'Project Lead',
        ReportingPerson: '1',
    },
    {
        Id: '6',
        Name: 'Elizabeth Roel',
        Designation: 'Project Lead',
        ReportingPerson: '1',
    },
    {
        Id: '7',
        Name: 'Aria Cruz',
        Designation: 'Project Lead',
        ReportingPerson: '18',
    },
    {
        Id: '8',
        Name: 'Eduardo Roel',
        Designation: 'Project Lead',
        ReportingPerson: '18',
    },
    {
        Id: '9',
        Name: 'Howard Snyd',
        Designation: 'Project Lead',
        ReportingPerson: '2',
    },
    {
        Id: '10',
        Name: 'Daniel Tonini',
        Designation: 'Project Lead',
        ReportingPerson: '2',
    },
    {
        Id: '11',
        Name: 'Nardo Batista',
        Designation: 'Project Lead',
        ReportingPerson: '3',
    },
    {
        Id: '12',
        Name: 'Michael Holz',
        Designation: 'Project Lead',
        ReportingPerson: '3',
    },
    {
        Id: '13',
        Name: 'Kloss Perrier',
        Designation: 'Project Lead',
        ReportingPerson: '4',
    },
    {
        Id: '14',
        Name: 'Liz Nixon',
        Designation: 'Project Lead',
        ReportingPerson: '4',
    },
    {
        Id: '16',
        Name: 'Paula Parente',
        Designation: 'Project Lead',
        ReportingPerson: '15',
    },
    {
        Id: '17',
        Name: 'Matti Kenna',
        Designation: 'Project Lead',
        ReportingPerson: '15',
    }
];
let items = new DataManager(data, new Query().take(7));

export default function App() {
    return (
        <DiagramComponent
            id="container"
            width={"100%"}
            height={"550px"}
            snapSettings={{ constraints: 0 }}

            //Uses layout to auto-arrange nodes on the diagram page
            layout={{
                //set layout type
                type: 'RadialTree',
                root: 'parent'
            }}

            //Configures data source for diagram
            dataSourceSettings={{
                id: 'Id',
                parentId: 'ReportingPerson',
                dataSource: items
            }}

            //Sets the default properties for nodes
            getNodeDefaults={(node) => {
                node.height = 20;
                node.width = 20;
                return node;
            }}

            //Sets the default properties for connectors
            getConnectorDefaults={(connector) => {
                connector.targetDecorator.shape = 'None';
                connector.type = 'Straight';
                return connector;
            }}
        >

            {/* Inject necessary services for the diagram */}
            <Inject services={[DataBinding, RadialTree]} />
        </DiagramComponent>
    );
}

// Render the App component into the 'diagram' element in the DOM
const root = ReactDOM.createRoot(document.getElementById("diagram"));
root.render(<App />);
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, Inject, ConnectorModel, DataBinding, NodeModel, RadialTree, DecoratorModel } from "@syncfusion/ej2-react-diagrams";
import { DataManager, Query } from "@syncfusion/ej2-data";

//Initializes data source
let data: object[] = [
  {
    Id: 'parent',
    Name: 'Maria Anders',
    Designation: 'Managing Director'
  },
  {
    Id: '1',
    Name: 'Ana Trujillo',
    Designation: 'Project Manager',
    ReportingPerson: 'parent',
  },
  {
    Id: '2',
    Name: 'Lino Rodri',
    Designation: 'Project Manager',
    ReportingPerson: 'parent',
  },
  {
    Id: '3',
    Name: 'Philip Cramer',
    Designation: 'Project Manager',
    ReportingPerson: 'parent',
  },
  {
    Id: '4',
    Name: 'Pedro Afonso',
    Designation: 'Project Manager',
    ReportingPerson: 'parent',
  },
  {
    Id: '15',
    Name: 'Paul Henriot',
    Designation: 'Project Manager',
    ReportingPerson: 'parent',
  },
  {
    Id: '18',
    Name: 'Laura Callahan',
    Designation: 'Project Manager',
    ReportingPerson: 'parent',
  },
  {
    Id: '5',
    Name: 'Anto Moreno',
    Designation: 'Project Lead',
    ReportingPerson: '1',
  },
  {
    Id: '6',
    Name: 'Elizabeth Roel',
    Designation: 'Project Lead',
    ReportingPerson: '1',
  },
  {
    Id: '7',
    Name: 'Aria Cruz',
    Designation: 'Project Lead',
    ReportingPerson: '18',
  },
  {
    Id: '8',
    Name: 'Eduardo Roel',
    Designation: 'Project Lead',
    ReportingPerson: '18',
  },
  {
    Id: '9',
    Name: 'Howard Snyd',
    Designation: 'Project Lead',
    ReportingPerson: '2',
  },
  {
    Id: '10',
    Name: 'Daniel Tonini',
    Designation: 'Project Lead',
    ReportingPerson: '2',
  },
  {
    Id: '11',
    Name: 'Nardo Batista',
    Designation: 'Project Lead',
    ReportingPerson: '3',
  },
  {
    Id: '12',
    Name: 'Michael Holz',
    Designation: 'Project Lead',
    ReportingPerson: '3',
  },
  {
    Id: '13',
    Name: 'Kloss Perrier',
    Designation: 'Project Lead',
    ReportingPerson: '4',
  },
  {
    Id: '14',
    Name: 'Liz Nixon',
    Designation: 'Project Lead',
    ReportingPerson: '4',
  },
  {
    Id: '16',
    Name: 'Paula Parente',
    Designation: 'Project Lead',
    ReportingPerson: '15',
  },
  {
    Id: '17',
    Name: 'Matti Kenna',
    Designation: 'Project Lead',
    ReportingPerson: '15',
  }
];
let items: DataManager = new DataManager(data as JSON[], new Query().take(7));

export default function App() {
  return (
    <DiagramComponent
      id="container"
      width={"100%"}
      height={"550px"}
      snapSettings={{ constraints: 0 }}

      //Uses layout to auto-arrange nodes on the diagram page
      layout={{
        //set layout type
        type: 'RadialTree',
        root: 'parent'
      }}

      //Configures data source for diagram
      dataSourceSettings={{
        id: 'Id',
        parentId: 'ReportingPerson',
        dataSource: items
      }}

      //Sets the default properties for nodes
      getNodeDefaults={(node: NodeModel) => {
        node.height = 20;
        node.width = 20;
        return node;
      }}

      //Sets the default properties for connectors
      getConnectorDefaults={(connector: ConnectorModel) => {
        (connector.targetDecorator as DecoratorModel).shape = 'None';
        connector.type = 'Straight';
        return connector;
      }}
    >

      {/* Inject necessary services for the diagram */}
      <Inject services={[DataBinding, RadialTree]} />
    </DiagramComponent>
  );
}

// Render the App component into the 'diagram' element in the DOM
const root = ReactDOM.createRoot(document.getElementById("diagram") as HTMLElement);
root.render(<App />);

Note: When converting a data source into a radial layout, inject both DataBinding and RadialTree modules in the diagram component.

Radial Tree with Nodes and Connectors

For scenarios requiring manual control over node creation and positioning, the radial tree layout can be applied to explicitly defined nodes and connectors. This approach offers greater flexibility for custom node styling and specific layout requirements.

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, Inject, DataBinding, RadialTree } from "@syncfusion/ej2-react-diagrams";
import { DataManager, Query } from "@syncfusion/ej2-data";

//Initializes data source
let data = [
    {
        Id: 'parent',
        Name: 'Maria Anders',
        Designation: 'Managing Director'
    },
    {
        Id: '1',
        Name: 'Ana Trujillo',
        Designation: 'Project Manager',
        ReportingPerson: 'parent',
    },
    {
        Id: '2',
        Name: 'Lino Rodri',
        Designation: 'Project Manager',
        ReportingPerson: 'parent',
    },
    {
        Id: '3',
        Name: 'Philip Cramer',
        Designation: 'Project Manager',
        ReportingPerson: 'parent',
    },
    {
        Id: '4',
        Name: 'Pedro Afonso',
        Designation: 'Project Manager',
        ReportingPerson: 'parent',
    },
    {
        Id: '15',
        Name: 'Paul Henriot',
        Designation: 'Project Manager',
        ReportingPerson: 'parent',
    },
    {
        Id: '18',
        Name: 'Laura Callahan',
        Designation: 'Project Manager',
        ReportingPerson: 'parent',
    },
    {
        Id: '5',
        Name: 'Anto Moreno',
        Designation: 'Project Lead',
        ReportingPerson: '1',
    },
    {
        Id: '6',
        Name: 'Elizabeth Roel',
        Designation: 'Project Lead',
        ReportingPerson: '1',
    },
    {
        Id: '7',
        Name: 'Aria Cruz',
        Designation: 'Project Lead',
        ReportingPerson: '18',
    },
    {
        Id: '8',
        Name: 'Eduardo Roel',
        Designation: 'Project Lead',
        ReportingPerson: '18',
    },
    {
        Id: '9',
        Name: 'Howard Snyd',
        Designation: 'Project Lead',
        ReportingPerson: '2',
    },
    {
        Id: '10',
        Name: 'Daniel Tonini',
        Designation: 'Project Lead',
        ReportingPerson: '2',
    },
    {
        Id: '11',
        Name: 'Nardo Batista',
        Designation: 'Project Lead',
        ReportingPerson: '3',
    },
    {
        Id: '12',
        Name: 'Michael Holz',
        Designation: 'Project Lead',
        ReportingPerson: '3',
    },
    {
        Id: '13',
        Name: 'Kloss Perrier',
        Designation: 'Project Lead',
        ReportingPerson: '4',
    },
    {
        Id: '14',
        Name: 'Liz Nixon',
        Designation: 'Project Lead',
        ReportingPerson: '4',
    },
    {
        Id: '16',
        Name: 'Paula Parente',
        Designation: 'Project Lead',
        ReportingPerson: '15',
    },
    {
        Id: '17',
        Name: 'Matti Kenna',
        Designation: 'Project Lead',
        ReportingPerson: '15',
    }
];
let items = new DataManager(data, new Query().take(7));

export default function App() {
    return (
        <DiagramComponent
            id="container"
            width={"100%"}
            height={"550px"}
            snapSettings={{ constraints: 0 }}

            //Uses layout to auto-arrange nodes on the diagram page
            layout={{
                //set layout type
                type: 'RadialTree',
                root: 'parent'
            }}

            //Configures data source for diagram
            dataSourceSettings={{
                id: 'Id',
                parentId: 'ReportingPerson',
                dataSource: items
            }}

            //Sets the default properties for nodes
            getNodeDefaults={(node) => {
                node.height = 20;
                node.width = 20;
                return node;
            }}

            //Sets the default properties for connectors
            getConnectorDefaults={(connector) => {
                connector.targetDecorator.shape = 'None';
                connector.type = 'Straight';
                return connector;
            }}
        >

            {/* Inject necessary services for the diagram */}
            <Inject services={[DataBinding, RadialTree]} />
        </DiagramComponent>
    );
}

// Render the App component into the 'diagram' element in the DOM
const root = ReactDOM.createRoot(document.getElementById("diagram"));
root.render(<App />);
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramComponent, Inject, ConnectorModel, DataBinding, NodeModel, RadialTree, DecoratorModel } from "@syncfusion/ej2-react-diagrams";
import { DataManager, Query } from "@syncfusion/ej2-data";

//Initializes data source
let data: object[] = [
  {
    Id: 'parent',
    Name: 'Maria Anders',
    Designation: 'Managing Director'
  },
  {
    Id: '1',
    Name: 'Ana Trujillo',
    Designation: 'Project Manager',
    ReportingPerson: 'parent',
  },
  {
    Id: '2',
    Name: 'Lino Rodri',
    Designation: 'Project Manager',
    ReportingPerson: 'parent',
  },
  {
    Id: '3',
    Name: 'Philip Cramer',
    Designation: 'Project Manager',
    ReportingPerson: 'parent',
  },
  {
    Id: '4',
    Name: 'Pedro Afonso',
    Designation: 'Project Manager',
    ReportingPerson: 'parent',
  },
  {
    Id: '15',
    Name: 'Paul Henriot',
    Designation: 'Project Manager',
    ReportingPerson: 'parent',
  },
  {
    Id: '18',
    Name: 'Laura Callahan',
    Designation: 'Project Manager',
    ReportingPerson: 'parent',
  },
  {
    Id: '5',
    Name: 'Anto Moreno',
    Designation: 'Project Lead',
    ReportingPerson: '1',
  },
  {
    Id: '6',
    Name: 'Elizabeth Roel',
    Designation: 'Project Lead',
    ReportingPerson: '1',
  },
  {
    Id: '7',
    Name: 'Aria Cruz',
    Designation: 'Project Lead',
    ReportingPerson: '18',
  },
  {
    Id: '8',
    Name: 'Eduardo Roel',
    Designation: 'Project Lead',
    ReportingPerson: '18',
  },
  {
    Id: '9',
    Name: 'Howard Snyd',
    Designation: 'Project Lead',
    ReportingPerson: '2',
  },
  {
    Id: '10',
    Name: 'Daniel Tonini',
    Designation: 'Project Lead',
    ReportingPerson: '2',
  },
  {
    Id: '11',
    Name: 'Nardo Batista',
    Designation: 'Project Lead',
    ReportingPerson: '3',
  },
  {
    Id: '12',
    Name: 'Michael Holz',
    Designation: 'Project Lead',
    ReportingPerson: '3',
  },
  {
    Id: '13',
    Name: 'Kloss Perrier',
    Designation: 'Project Lead',
    ReportingPerson: '4',
  },
  {
    Id: '14',
    Name: 'Liz Nixon',
    Designation: 'Project Lead',
    ReportingPerson: '4',
  },
  {
    Id: '16',
    Name: 'Paula Parente',
    Designation: 'Project Lead',
    ReportingPerson: '15',
  },
  {
    Id: '17',
    Name: 'Matti Kenna',
    Designation: 'Project Lead',
    ReportingPerson: '15',
  }
];
let items: DataManager = new DataManager(data as JSON[], new Query().take(7));

export default function App() {
  return (
    <DiagramComponent
      id="container"
      width={"100%"}
      height={"550px"}
      snapSettings={{ constraints: 0 }}

      //Uses layout to auto-arrange nodes on the diagram page
      layout={{
        //set layout type
        type: 'RadialTree',
        root: 'parent'
      }}

      //Configures data source for diagram
      dataSourceSettings={{
        id: 'Id',
        parentId: 'ReportingPerson',
        dataSource: items
      }}

      //Sets the default properties for nodes
      getNodeDefaults={(node: NodeModel) => {
        node.height = 20;
        node.width = 20;
        return node;
      }}

      //Sets the default properties for connectors
      getConnectorDefaults={(connector: ConnectorModel) => {
        (connector.targetDecorator as DecoratorModel).shape = 'None';
        connector.type = 'Straight';
        return connector;
      }}
    >

      {/* Inject necessary services for the diagram */}
      <Inject services={[DataBinding, RadialTree]} />
    </DiagramComponent>
  );
}

// Render the App component into the 'diagram' element in the DOM
const root = ReactDOM.createRoot(document.getElementById("diagram") as HTMLElement);
root.render(<App />);

Note: To use radial tree layout functionality, inject the RadialTree module in the diagram component.

Radial tree