Bezier Connector in EJ2 Angular Diagram control

Bezier segments are used to create curve segments and the curves are configurable either with the control points or with vectors.

To create a bezier segment, the segment.type is set as bezier and need to specify type for the connector. The following code example illustrates how to create a default bezier segment.

import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
import { DiagramComponent, DiagramModule, ConnectorModel, PointModel, OrthogonalSegmentModel } from '@syncfusion/ej2-angular-diagrams';

@Component({
imports: [
         DiagramModule
    ],

providers: [ ],
standalone: true,
    selector: "app-container",
    template: `<ejs-diagram #diagram id="diagram" width="100%" height="580px" >
        <e-connectors>
            <e-connector id='connector' type='Bezier' [sourcePoint]='sourcePoint' [targetPoint]='targetPoint' [segments]='segments'>
            </e-connector>
        </e-connectors>
    </ejs-diagram>`,
    encapsulation: ViewEncapsulation.None
})
export class AppComponent {
    @ViewChild("diagram")
    public diagram?: DiagramComponent;
    public sourcePoint?: PointModel;
    public targetPoint?: PointModel;
    public segments?: OrthogonalSegmentModel;
    ngOnInit(): void {
        this.sourcePoint = { x: 100, y: 100 };
        this.targetPoint = { x: 200, y: 200 };
        this.segments = [ { type: 'Bezier'} ];
    }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Bezier segment editing

  • A segment control point of the Bezier connector is used to change the bezier vectors and points of the connector.

Bezier Segment edit Gif

Control Points

  • Bezier control points can be positioned in two ways.

  • When setting control point positions using the The point1 and point2 properties, the control point remains fixed in its set position while dragging connector end points.
  • When setting control point positions using the vector1 and vector2 properties, the control point dynamically adjusts to maintain the angle and distance originally set while moving the connector end points.

Point

The point1 and point2 properties of bezier segment enable you to set the control points. The following code example illustrates how to configure the bezier segments with control points.

import { Component, ViewEncapsulation, OnInit, ViewChild } from '@angular/core';
import { DiagramComponent, Diagram, DiagramModule, ConnectorModel,  PointModel, OrthogonalSegmentModel,ConnectorEditing } from '@syncfusion/ej2-angular-diagrams';
Diagram.Inject(ConnectorEditing);
@Component({
imports: [
         DiagramModule
    ],

providers: [ ],
standalone: true,
    selector: "app-container",
    template: `<ejs-diagram #diagram id="diagram" width="100%" height="580px" >
        <e-connectors>
            <e-connector id='connector' type='Bezier' [sourcePoint]='sourcePoint' [targetPoint]='targetPoint' [segments]='segments'>
            </e-connector>
        </e-connectors>
    </ejs-diagram>`,
    encapsulation: ViewEncapsulation.None
})
export class AppComponent {
    @ViewChild("diagram")
    public diagram?: DiagramComponent;
    public sourcePoint?: PointModel;
    public targetPoint?: PointModel;
    public segments?: OrthogonalSegmentModel;
    ngOnInit(): void {
        this.sourcePoint = { x: 100, y: 200 };
        this.targetPoint = { x: 200, y: 100 };
        this.segments = [{
            type: 'Bezier',
            // First control point: an absolute position from the page origin
            point1: {
                x: 100,
                y: 100
            },
            // Second control point: an absolute position from the page origin
            point2: {
                x: 200,
                y: 200
            }
        }]
    }
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Bezier Control point set by point1 and point2

Vector

The vector1 and vector2 properties of bezier segment enable you to define the vectors. The following code illustrates how to configure a bezier curve with vectors.

import { Component, ViewEncapsulation, OnInit, ViewChild } from '@angular/core';
import { DiagramComponent, Diagram, DiagramModule,ConnectorModel, PointModel, OrthogonalSegmentModel,ConnectorEditing } from '@syncfusion/ej2-angular-diagrams';
Diagram.Inject(ConnectorEditing)
@Component({
imports: [
         DiagramModule
    ],

providers: [ ],
standalone: true,
    selector: "app-container",
    template: `<ejs-diagram #diagram id="diagram" width="100%" height="580px" >
        <e-connectors>
            <e-connector id='connector' type='Bezier' [sourcePoint]='sourcePoint' [targetPoint]='targetPoint' [segments]='segments'>
            </e-connector>
        </e-connectors>
    </ejs-diagram>`,
    encapsulation: ViewEncapsulation.None
})
export class AppComponent {
    @ViewChild("diagram")
    public diagram?: DiagramComponent;
    public sourcePoint?: PointModel;
    public targetPoint?: PointModel;
    public segments?: OrthogonalSegmentModel;
    ngOnInit(): void {
        this.sourcePoint = { x: 100, y: 100 };
        this.targetPoint = { x: 200, y: 200 };
        this.segments = [{
            type: 'Bezier',
            // Length and angle between the source point and the first control point
            vector1: {
                distance: 100,
                angle: 90
            },
            // Length and angle between the target point and the second control point
            vector2: {
                distance: 45,
                angle: 270
            }
        }]
    }
   
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Bezier Control point set by vector1 and vector1

Avoid overlapping with bezier

By default, when there are no segments defined for a bezier connector, the bezier segments will be created automatically and routed in such a way that avoids overlapping with the source and target nodes.

import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { DiagramModule } from '@syncfusion/ej2-angular-diagrams'



import { Component, ViewEncapsulation, OnInit, ViewChild } from '@angular/core';
import { DiagramComponent, Diagram, NodeModel, ConnectorModel,ConnectorEditing, ConnectorConstraints,BezierSegmentModel, PointPortModel, ControlPointsVisibility, PortVisibility, ShapeStyleModel } from '@syncfusion/ej2-angular-diagrams';
Diagram.Inject(ConnectorEditing);
@Component({
imports: [
         DiagramModule
    ],

providers: [ ],
standalone: true,
    selector: "app-container",
    template: `<ejs-diagram #diagram id="diagram" width="100%" height="600px" [getNodeDefaults]='getNodeDefaults' >
        <e-nodes>
            <e-node id='Start' [offsetX]=250 [offsetY]=150 [ports]='StartPort'>
                <e-node-annotations>
                    <e-node-annotation content="Start">
                    </e-node-annotation>
                </e-node-annotations>
            </e-node>
            <e-node id='End' [offsetX]=500 [offsetY]=200 [ports]='EndPort'>
                <e-node-annotations>
                    <e-node-annotation content="End">
                    </e-node-annotation>
                </e-node-annotations>
            </e-node>
        </e-nodes>
        <e-connectors>
            <e-connector id='connector1' type='Bezier' sourceID='Start' targetID='End'  sourcePortID='StartPort' targetPortID='EndPort' bezierSettings='bezierSettings' [constraints]='constraints'>
            </e-connector>
        </e-connectors>
    </ejs-diagram>`,
      encapsulation: ViewEncapsulation.None
})
export class AppComponent {
    @ViewChild("diagram")
    public diagram?: DiagramComponent;
    public StartPort?:PointPortModel[];
    public EndPort?:PointPortModel[];
    public bezierSettings?: any;
      ngOnInit(): void {
        this.StartPort = [{
            id: 'StartPort',
            visibility: PortVisibility.Visible,
            shape: 'Circle',
            offset: { x: 1, y: 0.5 },
            style: { strokeColor: '#366F8C', fill: '#366F8C' }
        }];
        this.EndPort = [{
            id: 'EndPort',
            visibility: PortVisibility.Visible,
            shape: 'Circle',
            offset: { x: 0, y: 0.5 },
            style: { strokeColor: '#366F8C', fill: '#366F8C' }
        }];
        this.bezierSettings = { controlPointsVisibility: ControlPointsVisibility.Source | ControlPointsVisibility.Target };
    }
        public getNodeDefaults(node: NodeModel | any): NodeModel {
        node.height = 100;
        node.width = 100;
        node.shape = { type: 'Basic', shape: 'Rectangle' };
        ((node as NodeModel).style as ShapeStyleModel).fill = "#6BA5D7";
        ((node as NodeModel).style as ShapeStyleModel).strokeColor = "White";
        return node;
    }

    constraints = ConnectorConstraints.Default | ConnectorConstraints.DragSegmentThumb;
   
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

Allow segment reset.

This feature allows users to choose whether to reset the control points of bezier segments when moving the source or target node. This decision empowers users to maintain control over the positioning of bezier curves, enhancing flexibility and precision in diagram editing.

With allow segment reset as true.

Allow Segment rest true

With allow segment reset as false.

Allow Segment rest false

import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
import { DiagramComponent, DiagramModule, Diagram, NodeModel, ConnectorModel, ConnectorEditing, ConnectorConstraints } from '@syncfusion/ej2-angular-diagrams';
Diagram.Inject(ConnectorEditing);

@Component({
    imports: [
        DiagramModule
    ],

    providers: [],
    standalone: true,
    selector: "app-container",
    template: `<ejs-diagram #diagram id="diagram" width="100%" height="600px" [getNodeDefaults]='getNodeDefaults' [getConnectorDefaults] ='getConnectorDefaults'>
         <e-nodes>
            <e-node id= 'Start' [offsetX]=250 [offsetY]=150>
                <e-node-annotations>
                    <e-node-annotation content="Start">
                    </e-node-annotation>
                </e-node-annotations>
            </e-node>
            <e-node id='End' [offsetX]=450 [offsetY]=300>
                <e-node-annotations>
                    <e-node-annotation content="End">
                    </e-node-annotation>
                </e-node-annotations>
            </e-node>
        </e-nodes>
        <e-connectors>
            <e-connector id='connector1' type='Bezier' sourceID='Start' targetID='End' [segments]="segments">
            </e-connector>
        </e-connectors>
    </ejs-diagram>`,
    encapsulation: ViewEncapsulation.None
})

export class AppComponent {

    @ViewChild("diagram")
    public diagram?: DiagramComponent;
    public getNodeDefaults(node: NodeModel): void {
        node.height = 100;
        node.width = 100;
        node.shape = { type: 'Basic', shape: 'Rectangle' };
        node.style = { fill: '#6BA5D7', strokeColor: 'white' };
    };

    public segments = [{
        type: 'Bezier',
        point1: { x: 450, y: 150 },
        point2: { x: 250, y: 250 },
    }];

    public getConnectorDefaults(connector: ConnectorModel): void {
        connector.targetDecorator = { shape: 'None' };
        connector.bezierSettings = { allowSegmentsReset: false };
        connector.constraints = ConnectorConstraints.Default | ConnectorConstraints.DragSegmentThumb;
    };
};
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));

How to customize Bezier Segment Thumb Size

Bezier segment thumbs default to size 10. This can be adjusted globally or for individual connectors using the segmentThumbSize property.
To change the thumb size for all Bezier connectors, set the segmentThumbSize property in the diagram’s model.
To customize the thumb size for a specific connector, disable the InheritSegmentThumbSize constraint, then set the desired segmentThumbSize.

import { Component, ViewEncapsulation, ViewChild } from '@angular/core';
import { DiagramComponent, Diagram, DiagramModule, ConnectorConstraints,NodeModel,ConnectorEditing, PointModel, OrthogonalSegmentModel } from '@syncfusion/ej2-angular-diagrams';
Diagram.Inject(ConnectorEditing);

@Component({
imports: [
         DiagramModule
    ],

providers: [ ],
standalone: true,
    selector: "app-container",
    template: `<ejs-diagram #diagram id="diagram" width="900px" height="500px"  [getNodeDefaults]  ='getNodeDefaults'  [segmentThumbSize]= 15>
          <e-nodes>
            <e-node id='node1' [offsetX]=150 [offsetY]=150 > </e-node>
            <e-node id='node2' [offsetX]=350 [offsetY]=400 > </e-node>
            <e-node id='node3' [offsetX]=550 [offsetY]=150 > </e-node>
            <e-node id='node4' [offsetX]=800 [offsetY]=400 > </e-node>
        </e-nodes>
        <e-connectors>
            <e-connector id='connector1' type='Bezier' sourceID='node1'  targetID='node2' [segments]='segments1' [constraints]='Constraints1'>
            </e-connector>
            <e-connector id='connector2' type='Bezier' sourceID='node3'  targetID='node4' [segments]='segments2' [constraints]='Constraints2' [segmentThumbSize] = 20 >
            </e-connector>
        </e-connectors>
    </ejs-diagram>`,
    encapsulation: ViewEncapsulation.None
})
export class AppComponent {
    @ViewChild("diagram")
    public diagram?: DiagramComponent;
    public sourcePoint?: PointModel;
    public targetPoint?: PointModel;
    public segments?: OrthogonalSegmentModel;
    ngOnInit(): void {
        
    }
    public getNodeDefaults(node: NodeModel): NodeModel {
        node.height = 100;
        node.width = 100;
        return node;
    }
    public segments1 = [
        {
            type: 'Bezier',
            point: { x: 200, y: 300 },
        },
        {
            type: 'Bezier',
            point: { x: 320, y: 400 }
        }
    ]

    public segments2 = [
        {
            type: 'Bezier',
            point: { x: 600, y: 300 },
        },
        {
            type: 'Bezier',
            point: { x: 320, y: 400 }
        }
    ]

    public Constraints1 =  ConnectorConstraints.Default | ConnectorConstraints.DragSegmentThumb

    public Constraints2 =  ConnectorConstraints.Default & ~(ConnectorConstraints.InheritSegmentThumbSize) | ConnectorConstraints.DragSegmentThumb

}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));