Interaction in React Diagram component

18 Mar 202424 minutes to read

Selection

Selector provides a visual representation of selected elements. It behaves like a container and allows to update the size, position, and rotation angle of the selected elements through interaction and by using program. Single or multiple elements can be selected at a time.

Single selection

An element can be selected by clicking that element. During single click, all previously selected items are cleared. The following image shows how the selected elements are visually represented.

Single Selection

  • While selecting the diagram elements, the following events can be used to do your customization.
  • When selecting/unselecting the diagram elements, the selectionChange event gets triggered.

Selecting a group

When a child element of any group is clicked, its contained group is selected instead of the child element. With consecutive clicks on the selected element, selection is changed from top to bottom in the hierarchy of parent group to its children.

Multiple selection

Multiple elements can be selected with the following ways:

  • Ctrl+Click

    During single click, any existing item in the selection list be cleared, and only the item clicked recently is there in the selection list. To avoid cleaning the old selected item, Ctrl key must be on hold when clicking.

  • Selection rectangle/rubber band selection

Clicking and dragging the diagram area allows to create a rectangular region. The elements that are covered under the rectangular region are selected at the end.

Multiple Rubberband Selection

Select/Unselect elements using program

The client-side methods select and clearSelection help to select or clear the selection of the elements at runtime. The following code example illustrates how to select or clear the selection of an item using program.

Get the current selected items from the nodes and connectors collection of the selectedItems property of the diagram model.

Select entire elements in diagram programmatically

The client-side method selectAll used to select all the elements such as nodes/connectors in the diagram. Refer to the following link which shows how to use selectAll method on the diagram.

Drag

  • An object can be dragged by clicking and dragging it. When multiple elements are selected, dragging any one of the selected elements move every selected element.
  • When you drag the elements in the diagram, the positionChange event gets triggered and to do customization in this event.

Drag

Resize

  • Selector is surrounded by eight thumbs. When dragging these thumbs, selected items can be resized.
  • When one corner of the selector is dragged, opposite corner is in a static position.
  • When a node is resized, the sizeChange event gets triggered.

Resize

Note: While dragging and resizing, the objects are snapped towards the nearest objects to make better alignments. For better alignments, refer to Snapping.

Customize the resize-thumb

You can change the size of the node resize thumb and the connector end point handle by using the handleSize property. The appearance such as fill, stroke, and stroke width of the node resize thumb and connector end point handle can be customized by overriding the e-diagram-resize-handle and e-diagram-endpoint-handle classes respectively.

import * as React from "react";
import * as ReactDOM from "react-dom";
import { DiagramComponent, } from "@syncfusion/ej2-react-diagrams";
let node = [{
        // Position of the node
        offsetX: 250,
        offsetY: 250,
        // Size of the node
        width: 100,
        height: 100,
        style: {
            fill: '#6BA5D7',
            strokeColor: 'white'
        }
    }];
function App() {
    return (<DiagramComponent id="container" width={'100%'} height={'600px'} nodes={node} selectedItems={{
            handleSize: 40,
        }}/>);
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
import * as React from "react";
import * as ReactDOM from "react-dom";
import {
    Diagram,
    DiagramComponent,
    ConnectorModel,
    NodeModel,
} from "@syncfusion/ej2-react-diagrams";
let node: NodeModel[] = [{
    // Position of the node
    offsetX: 250,
    offsetY: 250,
    // Size of the node
    width: 100,
    height: 100,
    style: {
        fill: '#6BA5D7',
        strokeColor: 'white'
    }
}];
function App() {
  return (
    <DiagramComponent
      id="container"
      width={'100%'}
      height={'600px'}
      nodes={node}
      selectedItems={{
        handleSize: 40,
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);

handleSize

Rotate

  • A rotate handler is placed above the selector. Clicking and dragging the handler in a circular direction lead to rotate the node.
  • The node is rotated with reference to the static pivot point.
  • Pivot thumb (thumb at the middle of the node) appears while rotating the node to represent the static point.

rotate

Connection editing

  • Each segment of a selected connector is editable with some specific handles/thumbs.

Note: For connector editing, you have to inject the ConnectorEditing module.

End point handles

Source and target points of the selected connectors are represented with two handles. Clicking and dragging those handles help you to adjust the source and target points.

Drag End Point Handles

  • If you drag the connector end points, then the following events can be used to do your customization.
  • When the connector source point is changed, the sourcePointChange event gets triggered.
  • When the connector target point is changed, the targetPointChange event gets triggered.
  • When you connect connector with ports/node or disconnect from it, the connectionChange event gets triggered.

Straight segment editing

  • End point of each straight segment is represented by a thumb that enables to edit the segment.
  • Any number of new segments can be inserted into a straight line by clicking, when Shift and Ctrl keys are pressed (Ctrl+Shift+Click).

Straight Segment Editing Addition

  • Straight segments can be removed by clicking the segment end point, when Ctrl and Shift keys are pressed (Ctrl+Shift+Click).

Straight Segment Editing Remove

Orthogonal thumbs

  • Orthogonal thumbs allow you to adjust the length of adjacent segments by clicking and dragging it.
  • When necessary, some segments are added or removed automatically, when dragging the segment. This is to maintain proper routing of orthogonality between segments.

orthogonal Segment Edit

Bezier thumbs

  • Bezier segments are annotated with two thumbs to represent the control points. Control points of the curve can be configured by clicking and dragging the control thumbs.

Bezier Segement Thumb

Drag and drop nodes over other elements

Diagram provides support to drop a node/connector over another node/connector. The drop event is raised to notify that an element is dropped over another one and it is disabled, by default. It can enabled with the constraints property.

User handles

  • User handles are used to add some frequently used commands around the selector. To create user handles, define and add them to the userHandles collection of the selectedItems property.
  • The name property of user handle is used to define the name of the user handle and its further used to find the user handle at runtime and do any customization.

Alignment

User handles can be aligned relative to the node boundaries. It has margin, offset, side, horizontalAlignment, and verticalAlignment settings. It is quite tricky when all four alignments are used together but gives more control over alignment.

Offset

The offset property of userHandles is used to align the user handle based on fractions. 0 represents top/left corner, 1 represents bottom/right corner, and 0.5 represents half of width/height.

Side

The side property of userHandles is used to align the user handle by using the Top, Bottom, Left, and Right options.

Horizontal and vertical alignments

The horizontalAlignment property of userHandles is used to set how the user handle is horizontally aligned at the position based on the offset. The verticalAlignment property is used to set how user handle is vertically aligned at the position.

Margin

Margin is an absolute value used to add some blank space in any one of its four sides. The userHandles can be displaced with the margin property.

Notification for the mouse button clicked

The diagram component notifies the mouse button clicked. For example, whenever the right mouse button is clicked, the clicked button is notified as right. The mouse click is notified with,

Notification Description
Left When the left mouse button is clicked, left is notified
Middle When the mouse wheel is clicked, middle is notified
Right When the right mouse button is clicked, right is notified
let diagramInstance: DiagramComponent;
// initialize Diagram component
function App() {
  return (
    <DiagramComponent
      id="container"
      ref={(diagram) => (diagramInstance = diagram)}
      width={'100%'}
      height={'600px'}
      click={(args: : IClickEventArgs) => {
        //Obtains the button clicked
        let button = args.button;
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);

Appearance

The appearance of the user handle can be customized by using the size, borderColor, backgroundColor, visible, pathData, and pathColor properties of the userHandles.

import * as React from "react";
import * as ReactDOM from "react-dom";
import { DiagramComponent, MoveTool, SelectorConstraints, randomId, cloneObject } from "@syncfusion/ej2-react-diagrams";
let diagramInstance;
let shape = {
    type: 'Basic',
    shape: 'Rectangle'
};
let node1 = [{
        id: 'node',
        offsetX: 100,
        offsetY: 100,
        shape: shape
    }];
let handles = [{
        name: 'clone',
        pathData: 'M60.3,18H27.5c-3,0-5.5,2.4-5.5,5.5v38.2h5.5V23.5h32.7V18z M68.5,28.9h-30c-3, 0-5.5,2.4-5.5,5.5v38.2c0,3,2.4,5.5,5.5,5.5h30c3,0,5.5-2.4,5.5-5.5V34.4C73.9,31.4,71.5,28.9,68.5,28.9z M68.5,72.5h-30V34.4h30V72.5z',
        visible: true,
        offset: 0,
        side: 'Bottom',
        pathColor: "white",
        margin: {
            top: 0,
            bottom: 0,
            left: 0,
            right: 0
        }
    }];
function App() {
    return (<DiagramComponent id="container" ref={diagram => (diagramInstance = diagram)} width={"100%"} height={"600px"} nodes={node1} selectedItems={{
            constraints: SelectorConstraints.UserHandle,
            userHandles: handles
        }} 
    //set Node default value
    getNodeDefaults={(node) => {
            node.height = 100;
            node.width = 100;
            node.style.fill = '#6BA5D7';
            node.style.strokeColor = '#6BA5D7';
            return node;
        }} 
    //set CustomTool
    getCustomTool={getTool}/>);
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);
function getTool(action) {
    let tool;
    if (action === 'clone') {
        tool = new CloneTool(diagramInstance.commandHandler);
    }
    return tool;
}
//Defines the clone tool used to copy Node/Connector
class CloneTool extends MoveTool {
    mouseDown(args) {
        let newObject;
        if (diagramInstance.selectedItems.nodes.length > 0) {
            newObject = cloneObject(diagramInstance.selectedItems.nodes[0]);
        }
        else {
            newObject = cloneObject(diagramInstance.selectedItems.connectors[0]);
        }
        newObject.id += randomId();
        diagramInstance.paste([newObject]);
        args.source = diagramInstance.nodes[diagramInstance.nodes.length - 1];
        args.sourceWrapper = args.source.wrapper;
        super.mouseDown(args);
        this.inAction = true;
    }
}
import * as React from "react";
import * as ReactDOM from "react-dom";
import {
    DiagramComponent,
    NodeModel,
    ConnectorModel,
    Diagram,
    BasicShapeModel,
    MoveTool,
    MouseEventArgs,
    IElement,
    UserHandleModel,
    ToolBase,
    SelectorConstraints,
    Actions,
    randomId,
    cloneObject,
    Node,
    Side,
    SnapConstraints
    } from "@syncfusion/ej2-react-diagrams";
let diagramInstance: DiagramComponent;
let shape: BasicShapeModel = {
    type: 'Basic',
    shape: 'Rectangle'
};
let node1: NodeModel[] = [{
    id: 'node',
    offsetX: 100,
    offsetY: 100,
    shape: shape
}];
let handles: UserHandleModel[] = [{
    name: 'clone',
    pathData: 'M60.3,18H27.5c-3,0-5.5,2.4-5.5,5.5v38.2h5.5V23.5h32.7V18z M68.5,28.9h-30c-3, 0-5.5,2.4-5.5,5.5v38.2c0,3,2.4,5.5,5.5,5.5h30c3,0,5.5-2.4,5.5-5.5V34.4C73.9,31.4,71.5,28.9,68.5,28.9z M68.5,72.5h-30V34.4h30V72.5z',
    visible: true,
    offset: 0,
    side: 'Bottom',
    pathColor: "white",
    margin: {
        top: 0,
        bottom: 0,
        left: 0,
        right: 0
    }
}];
function App() {
  return (
    <DiagramComponent id="container"  ref={diagram => (diagramInstance = diagram)}
    width = {
        "100%"
    }
    height = {
        "600px"
    }
    nodes = {
        node1
    }
    selectedItems = {
        {
              constraints: SelectorConstraints.UserHandle,
              userHandles: handles
        }
    }
    //set Node default value
    getNodeDefaults = {
        (node: NodeModel): NodeModel => {
            node.height = 100;
            node.width = 100;
            node.style.fill = '#6BA5D7';
            node.style.strokeColor = '#6BA5D7';
            return node;
        }
    }
    //set CustomTool
    getCustomTool = {
        getTool
    }
/>
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);

function getTool(action: string): ToolBase {
    let tool: ToolBase;
    if (action === 'clone') {
        tool = new CloneTool(diagramInstance.commandHandler);
    }
    return tool;
}
//Defines the clone tool used to copy Node/Connector
class CloneTool extends MoveTool {
    public mouseDown(args: MouseEventArgs): void {
        let newObject: any;
        if (diagramInstance.selectedItems.nodes.length > 0) {
            newObject = cloneObject(diagramInstance.selectedItems.nodes[0]) as NodeModel;
        } else {
            newObject = cloneObject(diagramInstance.selectedItems.connectors[0]) as ConnectorModel;
        }
        newObject.id += randomId();
        diagramInstance.paste([newObject]);
        args.source = diagramInstance.nodes[diagramInstance.nodes.length - 1] as IElement;
        args.sourceWrapper = args.source.wrapper;
        super.mouseDown(args);
        this.inAction = true;
    }
}

Zoom pan

  • When a large diagram is loaded, only certain portion of the diagram is visible. The remaining portions are clipped. Clipped portions can be explored by scrolling the scrollbars or panning the diagram.
  • Diagram can be zoomed in or out by using Ctrl + mouse wheel.
  • When the diagram is zoomed or panned, the scrollChange event gets triggered.

Zoom Pan

Zoom pan status

Diagram provides the support to notify the pan status of the zoom pan tool. When ever the diagram is panning the scrollChange event is triggered and hence the pan status can be obtained. The pan status is notified with Start, Progress, and Completed.

Pan Status Description
Start When the mouse is clicked and dragged the status is notified as start.
Progress When the mouse is in motion the status is notified as progress.
Completed When panning is stopped the status is notified with completed.
let diagramInstance: DiagramComponent;
// initialize Diagram component
function App() {
  return (
    <DiagramComponent
      id="container"
      ref={(diagram) => (diagramInstance = diagram)}
      width={'100%'}
      height={'600px'}
      scrollChange={(args: IScrollChangeEventArgs) => {
        //Obtains the pan status
        let panStatus = args.panState;
      }}
      created={() => {
        diagramInstance.tool = DiagramTools.ZoomPan;
        diagramInstance.dataBind();
      }}
    />
  );
}
const root = ReactDOM.createRoot(document.getElementById('diagram'));
root.render(<App />);

Keyboard

Diagram provides support to interact with the elements with key gestures. By default, some in-built commands are bound with a relevant set of key combinations.

The following table illustrates those commands with the associated key values.

Shortcut Key Command Description
Ctrl + A selectAll Select all nodes/connectors in the diagram.
Ctrl + C copy Copy the diagram selected elements.
Ctrl + V paste Pastes the copied elements.
Ctrl + X cut Cuts the selected elements.
Ctrl + Z undo Reverses the last editing action performed on the diagram.
Ctrl + Y redo Restores the last editing action when no other actions have occurred since the last undo on the diagram.
Delete delete Deletes the selected elements.
Ctrl/Shift + Click on object   Multiple selection (Selector binds all selected nodes/connectors).
Up Arrow nudge(“up”) nudgeUp: Moves the selected elements towards up by one pixel.
Down Arrow nudge(“down”) nudgeDown: Moves the selected elements towards down by one pixel.
Left Arrow nudge(“left”) nudgeLeft: Moves the selected elements towards left by one pixel.
Right Arrow nudge(“right”) nudgeRight: Moves the selected elements towards right by one pixel.
Ctrl + MouseWheel zoom Zoom (Zoom in/Zoom out the diagram).
F2 startLabelEditing Starts to edit the label of selected element.
Esc endLabelEditing Sets the label mode as view and stops editing.
Tab Tab to Focus Select the diagram element based on the rendering order when using the “Tab” key.
Shift + Tab Go to Previous Object This command is employed to shift the selection to the preceding object based on the z-order.
Control + B Bold Toggle bold formatting for the selected text.
Control + I Italic Toggle italic formatting for the selected text.
Control + U Underline Toggle underline formatting for the selected text.
Control + D Duplicate Duplicate a selected shape.
Control + G Group Group together multiple selected shapes, allowing them to be treated as a single shape.
Control + Shift + U UnGroup Ungroup shapes within a previously grouped selection.
Control + R Rotate clockwise Rotate the selected nodes in clockwise.
Control + L Rotate anti-clockwise Rotate the selected nodes in counterclockwise.
Control + H Flip Horizontal Flip the selected elements horizontally.
Control + J Flip Vertical Flip the selected elements vertically.
Control + 1 Pointer tool Activate the pointer tool.
Control + 2 Text tool Activate the text tool.
Control + 3 Connector tool Activate the connector tool.
Control + 5 Freeform tool Activate the freeform tool.
Control + 6 Line tool Activate the polyline tool.
Control + + Zoom In Zoom in the diagram.
Control + - Zoom Out Zoom out the diagram.
Shift + Up Arrow Up Moves the selected elements towards up by 5 pixel.
Shift + Down Arrow Down Moves the selected elements towards down by 5 pixel.
Shift + Left Arrow Left Moves the selected elements towards left by 5 pixel.
Shift + Right Arrow Right Moves the selected elements towards right by 5 pixel.
Control + Shift + L Align Text Left Align the selected text to the left.
Control + Shift + C Center Text Horizontally Center the selected text horizontally.
Control + Shift + R Align Text Right Align the selected text to the right.
Control + Shift + J Justify Text Horizontally Justify the selected text, aligning it to both the left and right margins.
Control + Shift + E Top-align Text Vertically Align the selected text to the top vertically.
Control + Shift + M Center Text Vertically Center the selected text vertically.
Control + Shift + V Bottom-align Text Vertically Align the selected text to the bottom vertically.
Control + Shift + B Send To Back Send the selected shape backward in the stacking order, making it appear behind other shapes.
Control + Shift + F Bring To Front Bring the selected shape forward in the stacking order, making it appear in front of other shapes.
Control + [ Send Backward Move the selected shape one step backward in the layer order.
Control + ] Bring Forward Move the selected shape one step forward in the layer order.

See Also