Tools in React Diagram Component

21 Oct 202524 minutes to read

The React Diagram component provides a comprehensive set of interactive tools that enable users to create, modify, and navigate diagrams efficiently. These tools facilitate real-time interaction with diagram elements through mouse and keyboard operations.

Overview

The diagram control offers three primary tool categories:

  • Select: Choose and manipulate specific elements within the diagram.
  • Pan: Navigate the diagram view to different areas without modifying elements.
  • Draw: Create new shapes, connectors, and freehand drawings on the diagram surface.

These tools are essential for building complex diagrams and provide the foundation for user interaction within the diagram environment.

Drawing Tools

Drawing tools enable real-time creation of diagram elements by clicking and dragging on the diagram canvas. All drawing operations are configured through the drawingObject property and activated using the tool property.

Draw Nodes

To draw shapes during runtime, configure the JSON representation of the desired shape in the drawingObject property and set the tool to drawing mode. The following example demonstrates how to draw a rectangle shape:

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramTools, DiagramComponent } from '@syncfusion/ej2-react-diagrams';
let diagramInstance;
function App() {
  return (
    <DiagramComponent
      id="container"
      ref={(diagram) => (diagramInstance = diagram)}
      width={700}
      height={700}
      created={() => {
        //JSON to create a rectangle
        let drawingshape = {
          type: 'Basic',
          shape: 'Rectangle',
        };
        let node = {
          shape: drawingshape,
        };
        diagramInstance.drawingObject = node;
        //To draw an object once, activate draw once
        diagramInstance.tool = DiagramTools.ContinuousDraw;
        diagramInstance.dataBind();
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import {
  BasicShapeModel,
  NodeModel,
  DiagramTools,
  DiagramComponent,
} from '@syncfusion/ej2-react-diagrams';
let diagramInstance: DiagramComponent;
function App() {
  return (
    <DiagramComponent
      id="container"
      ref={(diagram) => (diagramInstance = diagram)}
      width={700}
      height={700}
      created={() => {
        //JSON to create a rectangle
        let drawingshape: BasicShapeModel = {
          type: 'Basic',
          shape: 'Rectangle',
        };
        let node: NodeModel = {
          shape: drawingshape,
        };
        diagramInstance.drawingObject = node;
        //To draw an object once, activate draw once
        diagramInstance.tool = DiagramTools.ContinuousDraw;
        diagramInstance.dataBind();
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);

Path shapes can be drawn using the same approach with custom path data. The following example shows how to draw a path shape:

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import {
  DiagramTools,
  DiagramComponent,
} from '@syncfusion/ej2-react-diagrams';
let diagramInstance;
function App() {
  return (
    <DiagramComponent
      id="container"
      ref={(diagram) => (diagramInstance = diagram)}
      width={700}
      height={700}
      created={() => {
        let node = {
            id: "Path",
            style: {
                fill: "#fbe172"
            },
            annotations: [{
                content: "Path"
            }],
            shape: {
                type: 'Path',
                data: 'M13.560 67.524 L 21.941 41.731 L 0.000 25.790 L 27.120 25.790 L 35.501 0.000 L 43.882 25.790 L 71.000 25.790 L 49.061 41.731 L 57.441 67.524 L 35.501 51.583 z'
            }
        };
        diagramInstance.drawingObject = node;
        //To draw an object once, activate draw once
        diagramInstance.tool = DiagramTools.ContinuousDraw;
        diagramInstance.dataBind();
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import {
  NodeModel,
  DiagramTools,
  DiagramComponent,
} from '@syncfusion/ej2-react-diagrams';
let diagramInstance: DiagramComponent;
function App() {
  return (
    <DiagramComponent
      id="container"
      ref={(diagram) => (diagramInstance = diagram)}
      width={700}
      height={700}
      created={() => {
        let node: NodeModel = {
            id: "Path",
            style: {
                fill: "#fbe172"
            },
            annotations: [{
                content: "Path"
            }],
            shape: {
                type: 'Path',
                data: 'M13.560 67.524 L 21.941 41.731 L 0.000 25.790 L 27.120 25.790 L 35.501 0.000 L 43.882 25.790 L 71.000 25.790 L 49.061 41.731 L 57.441 67.524 L 35.501 51.583 z'
            }
        };
        diagramInstance.drawingObject = node;
        //To draw an object once, activate draw once
        diagramInstance.tool = DiagramTools.ContinuousDraw;
        diagramInstance.dataBind();
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);

Text Nodes

Similarly, you can draw a text node by setting the type of shape as ‘Text’ in the drawingObject property. The text node includes a content property that defines the displayed text. Users can add or modify the content after completing the drawing operation:

import * as React from "react";
import * as ReactDOM from "react-dom";
import {
    DiagramTools,
    DiagramComponent
} from "@syncfusion/ej2-react-diagrams";
let diagramInstance;
function App() {
  return (
    <DiagramComponent
      id="container"
      ref={(diagram) => (diagramInstance = diagram)}
      width={700}
      height={700}
      created={() => {
        //JSON to create a text
        let node = {
        shape: {
                type: 'Text',
            }
        };
        diagramInstance.drawingObject = node;
        //To draw an object once, activate draw once
        diagramInstance.tool = DiagramTools.DrawOnce;
        diagramInstance.dataBind();
      }}
      //customize the appearance of the shape
      getNodeDefaults={(obj, diagramInstance) => {
        obj.borderWidth = 1;
        obj.style = {
          fill: '#6BA5D7',
          strokeWidth: 2,
          strokeColor: '#6BA5D7',
        };
        return obj;
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
import * as React from "react";
import * as ReactDOM from "react-dom";
import {
    TextModel,
    NodeModel,
    DiagramTools,
    DiagramComponent
} from "@syncfusion/ej2-react-diagrams";
let diagramInstance: DiagramComponent;
function App() {
  return (
    <DiagramComponent
      id="container"
      ref={(diagram) => (diagramInstance = diagram)}
      width={700}
      height={700}
      created={() => {
        //JSON to create a text
        let node: NodeModel = {
        shape: {
                type: 'Text',
            } as TextModel
        };
        diagramInstance.drawingObject = node;
        //To draw an object once, activate draw once
        diagramInstance.tool = DiagramTools.DrawOnce;
        diagramInstance.dataBind();
      }}
      //customize the appearance of the shape
      getNodeDefaults={(obj, diagramInstance) => {
        obj.borderWidth = 1;
        obj.style = {
          fill: '#6BA5D7',
          strokeWidth: 2,
          strokeColor: '#6BA5D7',
        };
        return obj;
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);

Draw Connectors

Connectors are drawn by defining the connector configuration in the drawingObject property. The drawing tool supports various connector types including straight, orthogonal, and bezier connectors:

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import {
  DiagramTools,
  DiagramComponent,
} from '@syncfusion/ej2-react-diagrams';
let diagramInstance;
function App() {
  return (
    <DiagramComponent
      id="container"
      ref={(diagram) => (diagramInstance = diagram)}
      width={700}
      height={700}
      created={() => {
        //JSON to create a Connector
        let connectors = {
          id: 'connector1',
          type: 'Straight',
          segments: [
            {
              type: 'polyline',
            },
          ],
        };
        diagramInstance.drawingObject = connectors;
        //To draw an object once, activate draw once
        diagramInstance.tool = DiagramTools.ContinuousDraw;
        diagramInstance.dataBind();
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import {
  ConnectorModel,
  DiagramTools,
  DiagramComponent,
} from '@syncfusion/ej2-react-diagrams';
let diagramInstance;
function App() {
  return (
    <DiagramComponent
      id="container"
      ref={(diagram) => (diagramInstance = diagram)}
      width={700}
      height={700}
      created={() => {
        //JSON to create a Connector
        let connectors: ConnectorModel = {
          id: 'connector1',
          type: 'Straight',
          segments: [
            {
              type: 'polyline',
            },
          ],
        };
        diagramInstance.drawingObject = connectors;
        //To draw an object once, activate draw once
        diagramInstance.tool = DiagramTools.ContinuousDraw;
        diagramInstance.dataBind();
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);

Polygon Shapes

The diagram supports interactive polygon creation through point-and-click interaction. Users can define custom shapes with multiple sides by specifying vertices directly on the diagram canvas. To enable polygon drawing, set the drawingObject type as Polygon:

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import {
  DiagramTools,
  DiagramComponent,
} from '@syncfusion/ej2-react-diagrams';
let diagramInstance;
function App() {
  return (
    <DiagramComponent
      id="container"
      ref={(diagram) => (diagramInstance = diagram)}
      width={700}
      height={700}
      created={() => {
        let drawingshape = {
          type: 'Basic',
          shape: 'Polygon',
        };
        //JSON to create a polygon
        let node = {
          shape: drawingshape,
        };
        diagramInstance.drawingObject = node;
        //To draw an object once, activate draw once
        diagramInstance.tool = DiagramTools.DrawOnce;
        diagramInstance.dataBind();
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import {
  BasicShapeModel,
  DiagramTools,
  DiagramComponent,
} from '@syncfusion/ej2-react-diagrams';
let diagramInstance;
function App() {
  return (
    <DiagramComponent
      id="container"
      ref={(diagram) => (diagramInstance = diagram)}
      width={700}
      height={700}
      created={() => {
        let drawingshape: BasicShapeModel = {
          type: 'Basic',
          shape: 'Polygon',
        };
        //JSON to create a polygon
        let node = {
          shape: drawingshape,
        };
        diagramInstance.drawingObject = node;
        //To draw an object once, activate draw once
        diagramInstance.tool = DiagramTools.DrawOnce;
        diagramInstance.dataBind();
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);

Polygon drawing

Polyline Connectors

Polyline connectors enable creation of multi-segment connections with straight lines and angled vertices. Users can interactively add control points by clicking on the diagram canvas. To draw polyline connectors, set the drawingObject type as Polyline:

The following code illustrates how to draw a polyline connector.

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import {
  DiagramTools,
  DiagramComponent,
} from '@syncfusion/ej2-react-diagrams';
let diagramInstance;
function App() {
  return (
    <DiagramComponent
      id="container"
      ref={(diagram) => (diagramInstance = diagram)}
      width={700}
      height={700}
      created={() => {
        let connector = {
          id: 'connector1',
          type: 'Polyline',
        };
        diagramInstance.drawingObject = connector;
        //To draw an object once, activate draw once
        diagramInstance.tool = DiagramTools.DrawOnce;
        diagramInstance.dataBind();
      }}
      //customize the appearance of the shape
      getNodeDefaults={(obj, diagramInstance) => {
        obj.borderWidth = 1;
        obj.style = {
          fill: '#6BA5D7',
          strokeWidth: 2,
          strokeColor: '#6BA5D7',
        };
        return obj;
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
import * as React from "react";
import * as ReactDOM from "react-dom";
import {
    ConnectorModel,
    DiagramTools,
    DiagramComponent
} from "@syncfusion/ej2-react-diagrams";
let diagramInstance: DiagramComponent;
function App() {
  return (
    <DiagramComponent
      id="container"
      ref={(diagram) => (diagramInstance = diagram)}
      width={700}
      height={700}
      created = {
            () => {
                let connector: ConnectorModel = {
                    id: 'connector1',
                    type: 'Polyline'
                };
                diagramInstance.drawingObject = connector;
                //To draw an object once, activate draw once
                diagramInstance.tool = DiagramTools.DrawOnce;
                diagramInstance.dataBind();
            }
        }
      //customize the appearance of the shape
      getNodeDefaults={(obj, diagramInstance) => {
        obj.borderWidth = 1;
        obj.style = {
          fill: '#6BA5D7',
          strokeWidth: 2,
          strokeColor: '#6BA5D7',
        };
        return obj;
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);

The segments of a polyline connector can be adjusted at runtime by dragging the segment thumb, as shown in the image below. To enable segment editing, you should set the DragSegmentThumb constraint for the connector.

Polyline connector drawing

NOTE

To make the segment thumb visible, inject the ConnectorEditing module into the diagram.

Freehand Drawing

The diagram supports free-hand drawing, allowing users to draw anything independently on the diagram page. Free-hand drawing is enabled by setting the type of the drawingObject property to ‘Freehand’.

The following code illustrates how to perform freehand drawing:

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { DiagramTools, DiagramComponent } from '@syncfusion/ej2-react-diagrams';
let diagramInstance;
function App() {
  return (
    <DiagramComponent
      id="container"
      ref={(diagram) => (diagramInstance = diagram)}
      width={700}
      height={700}
      created={() => {
        //JSON to create a Connector
        let connectors = {
          id: 'connector1',
          type: 'Freehand',
        };
        diagramInstance.drawingObject = connectors;
        //To draw an object once, activate draw once
        diagramInstance.tool = DiagramTools.DrawOnce;
        diagramInstance.dataBind();
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
import * as React from "react";
import * as ReactDOM from "react-dom";
import {
    ConnectorModel,
    DiagramTools,
    DiagramComponent
} from "@syncfusion/ej2-react-diagrams";
let diagramInstance: DiagramComponent;
function App() {
  return (
    <DiagramComponent
      id="container"
      ref={(diagram) => (diagramInstance = diagram)}
      width={700}
      height={700}
      created={() => {
        //JSON to create a Connector
        let connectors: ConnectorModel = {
          id: 'connector1',
          type: 'Freehand',
        };
        diagramInstance.drawingObject = connectors;
        //To draw an object once, activate draw once
        diagramInstance.tool = DiagramTools.DrawOnce;
        diagramInstance.dataBind();
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);

The segments of a freehand connector can be adjusted at runtime by dragging the segment thumb, as shown in the image below. To enable segment editing, you should set the DragSegmentThumb constraint for the connector.

Freehand connector drawing

Tool Selection and Precedence

The diagram supports multiple tool configurations that can be combined for different interaction scenarios. When multiple tools are enabled simultaneously, the system follows a specific precedence order to determine which tool takes priority:

Tool Precedence Hierarchy

The following table shows the precedence order from highest to lowest priority:

Precedence Tool Description
1st ContinuesDraw Enables continuous drawing mode. Once activated, prevents all other interactions until deactivated.
2nd DrawOnce Allows drawing a single element. After completion, automatically enables SingleSelect and MultipleSelect tools.
3rd ZoomPan Enables diagram panning. When combined with SingleSelect, panning activates when cursor hovers over empty diagram areas.
4th MultipleSelect Enables selection of multiple elements. When combined with ZoomPan, selection takes priority over panning when hovering over elements.
5th SingleSelect Enables selection of individual elements.
6th None Disables all interactive tools.

These tools provide flexibility and functionality for creating and interacting with elements within the diagram interface.

Zoom Pan Tool

The pan tool enables users to navigate large diagrams by dragging the view area. To activate panning mode, set the tool property to ZoomPan:

import * as React from "react";
import * as ReactDOM from "react-dom";
import {
    DiagramComponent,
    DiagramTools,
} from "@syncfusion/ej2-react-diagrams";
let diagramInstance;
let nodes = [{
       id: 'Start',
        width: 140,
        height: 50,
        offsetX: 300,
        offsetY: 50,
        annotations: [{
            id: 'label1',
            content: 'Start'
        }],
        shape: {
            type: 'Flow',
            shape: 'Terminator'
        }
        },
        {
        id: 'Init',
        width: 140,
        height: 50,
        offsetX: 300,
        offsetY: 140,
        annotations: [{
            id: 'label2',
            content: 'End'
        }],
        shape: {
            type: 'Flow',
            shape: 'Process'
        },
        annotations: [{
            content: 'var i = 0;'
        }]
    }
];
let connectors = [{
    // Name of the connector
    id: "connector1",
    style: {
        strokeColor: '#6BA5D7',
        fill: '#6BA5D7',
        strokeWidth: 2
    },
    targetDecorator: {
        style: {
            fill: '#6BA5D7',
            strokeColor: '#6BA5D7'
        }
    },
    // ID of the source and target nodes
    sourceID: "Start",
    targetID: "Init",
    connectorSpacing: 7,
    type: 'Orthogonal'
}];
function App() {
  return (
    <DiagramComponent
      id="container"
      ref={(diagram) => (diagramInstance = diagram)}
      width={700}
      height={700}
      nodes={nodes}
      connectors={connectors}
      tool={DiagramTools.DrawOnce | DiagramTools.ZoomPan}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
import * as React from "react";
import * as ReactDOM from "react-dom";
import {
    DiagramComponent,
    DiagramTools,
    ConnectorModel,
    NodeModel,
} from "@syncfusion/ej2-react-diagrams";
let diagramInstance: DiagramComponent;
let nodes: NodeModel[] = [{
       id: 'Start',
        width: 140,
        height: 50,
        offsetX: 300,
        offsetY: 50,
        annotations: [{
            id: 'label1',
            content: 'Start'
        }],
        shape: {
            type: 'Flow',
            shape: 'Terminator'
        }
        },
        {
        id: 'Init',
        width: 140,
        height: 50,
        offsetX: 300,
        offsetY: 140,
        annotations: [{
            id: 'label2',
            content: 'End'
        }],
        shape: {
            type: 'Flow',
            shape: 'Process'
        },
        annotations: [{
            content: 'var i = 0;'
        }]
    }
];
let connectors: ConnectorModel[] = [{
    // Name of the connector
    id: "connector1",
    style: {
        strokeColor: '#6BA5D7',
        fill: '#6BA5D7',
        strokeWidth: 2
    },
    targetDecorator: {
        style: {
            fill: '#6BA5D7',
            strokeColor: '#6BA5D7'
        }
    },
    // ID of the source and target nodes
    sourceID: "Start",
    targetID: "Init",
    connectorSpacing: 7,
    type: 'Orthogonal'
}];
function App() {
  return (
    <DiagramComponent
      id="container"
      ref={(diagram) => (diagramInstance = diagram)}
      width={700}
      height={700}
      nodes={nodes}
      connectors={connectors}
      tool={DiagramTools.DrawOnce | DiagramTools.ZoomPan}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);

NOTE

Please note that panning the diagram is not possible when ‘multiplePage’ is set to false if any diagram object (node or connector) is outside the defined page break area.

Events

The elementDraw event triggers whenever users create nodes or connectors using drawing tools. This event provides access to the newly created element and enables custom logic during the drawing process:

import * as React from "react";
import * as ReactDOM from "react-dom";
import {
    DiagramComponent,
    DiagramTools
} from "@syncfusion/ej2-react-diagrams";
let diagramInstance;
function App() {
  return (
    <DiagramComponent
      id="container"
      ref={(diagram) => (diagramInstance = diagram)}
      width={700}
      height={700}
      created={() => {
         //JSON to create a rectangle
         let drawingshape = {
            type: 'Basic',
            shape: 'Rectangle',
          };
          let node = {
            shape: drawingshape,
          };
          diagramInstance.drawingObject = node;
          //To draw an object once, activate draw once
          diagramInstance.tool = DiagramTools.DrawOnce;
          diagramInstance.dataBind();
      }}
      elementDraw={(args) => {
          if(args.state === 'Completed'){
            alert('Element Draw Rectangle');
          }
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
import * as React from "react";
import * as ReactDOM from "react-dom";
import {
    NodeModel,
    DiagramTools,
    DiagramComponent,
    BasicShapeModel,
    IElementDrawEventArgs
} from "@syncfusion/ej2-react-diagrams";
let diagramInstance: DiagramComponent;
function App() {
  return (
    <DiagramComponent
      id="container"
      ref={(diagram) => (diagramInstance = diagram)}
      width={700}
      height={700}
      created={() => {
         //JSON to create a rectangle
         let drawingshape: BasicShapeModel = {
            type: 'Basic',
            shape: 'Rectangle',
          };
          let node: NodeModel = {
            shape: drawingshape,
          };
          diagramInstance.drawingObject = node;
          //To draw an object once, activate draw once
          diagramInstance.tool = DiagramTools.DrawOnce;
          diagramInstance.dataBind();
      }}
      elementDraw={(args: IElementDrawEventArgs) => {
          if(args.state === 'Completed'){
            alert('Element Draw Rectangle');
          }
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);