Connectors

Connectors are smart connection lines that link items via ports. They automatically route around obstacles and update when connected items move.

Creating Connectors

Connect Two Items

The simplest way to connect items - automatically selects the best ports:

const connector = app.diagramSystem.connect(sourceItem, targetItem, {
  routing: 'orthogonal',
  lineColor: '#60a5fa',
  headStyle: 'classic'
});

Connect Specific Ports

For precise control, connect specific ports:

const sourcePort = app.diagramSystem.getPort(sourceItem, 'bottom');
const targetPort = app.diagramSystem.getPort(targetItem, 'top');

const connector = app.diagramSystem.connectPorts(sourcePort, targetPort, {
  routing: 'curved',
  label: 'data flow'
});

Routing Styles

Style Description Best For
direct Straight line Simple connections
orthogonal Right-angle segments Technical diagrams, flowcharts
curved Smooth bezier curve Organic diagrams, mind maps
// Direct routing
app.diagramSystem.connect(a, b, { routing: 'direct' });

// Orthogonal routing (default)
app.diagramSystem.connect(a, b, { routing: 'orthogonal' });

// Curved routing
app.diagramSystem.connect(a, b, { routing: 'curved', curvature: 0.5 });

Curvature Control

For curved connectors, control the curve intensity:

app.diagramSystem.connect(a, b, {
  routing: 'curved',
  curvature: 0.3   // 0.1 = tight, 1.0 = very curved
});

Line Styles

Style Description
solid Continuous line
dashed Dashed line pattern
dotted Dotted line pattern
// Dashed connector
app.diagramSystem.connect(a, b, { lineStyle: 'dashed' });

// Dotted connector
app.diagramSystem.connect(a, b, { lineStyle: 'dotted' });

Arrowhead Styles

Style Description
classic Filled triangle (default)
stealth Diamond with notch
sharp Elongated point
open V-shape stroke only
diamond Diamond shape
circle Filled circle
none No arrowhead
// Classic arrowhead
app.diagramSystem.connect(a, b, { headStyle: 'classic' });

// Stealth arrowhead
app.diagramSystem.connect(a, b, { headStyle: 'stealth' });

// Bidirectional arrows
app.diagramSystem.connect(a, b, {
  headStyle: 'classic',
  tailStyle: 'classic'   // Arrow at start too
});

Connector Configuration

Full configuration options:

app.diagramSystem.connect(sourceItem, targetItem, {
  // Routing
  routing: 'orthogonal',     // 'direct', 'orthogonal', 'curved'
  curvature: 0.5,            // For curved: 0.1 to 1.0
  smoothness: 60,            // Smoothing factor: 0-100

  // Line appearance
  lineColor: '#60a5fa',
  lineWidth: 3,
  lineStyle: 'solid',        // 'solid', 'dashed', 'dotted'

  // Arrowheads
  headStyle: 'classic',      // Head at target
  tailStyle: 'none',         // Head at source
  headSize: 1.0,             // Size multiplier

  // Bolt animation
  boltEnabled: true,
  boltColor: '#fbbf24',
  boltSize: 2,
  boltSpeed: 1.0,

  // Label
  label: 'Connection',
  labelPosition: 0.5         // 0-1 along path
});

Labels

Add labels to connectors:

// With label at creation
const connector = app.diagramSystem.connect(a, b, {
  label: 'data flow'
});

// Add/update label later
connector.setLabel('updated label', 0.5);  // 0.5 = middle of path

Waypoints

Add manual routing points for complex paths:

// Add waypoint
connector.addWaypoint(new paper.Point(300, 200));
connector.addWaypoint(new paper.Point(300, 400), 0);  // Insert at index 0

// Update waypoint
connector.updateWaypoint(0, new paper.Point(350, 200));

// Remove waypoint
connector.removeWaypoint(0);

Self-Connections

Connect an item to itself (loops):

// Self-connection creates a visual loop
const loopConnector = app.diagramSystem.connect(item, item, {
  routing: 'curved'
});
// Automatically creates an outward-facing loop

Updating Style

Update connector appearance after creation:

connector.updateStyle({
  lineColor: '#ef4444',
  headStyle: 'stealth',
  lineWidth: 4
});

Selection & Editing

// Select a connector
connector.setSelected(true);

// When selected, curved connectors show a control handle
// Drag the handle to adjust curvature

// Waypoint handles appear for editing manual routes
connector.showWaypointHandles(true);

Automatic Updates

Connectors automatically refresh when connected items move:

// Move an item - connectors update automatically
sourceItem.position = new paper.Point(500, 300);

// Manual refresh if needed
connector.refresh();

Serialization

// Serialize a connector
const data = connector.serialize();
// Returns: {
//   id, sourceItemId, targetItemId,
//   sourcePortPosition, targetPortPosition,
//   waypoints, style, label, labelPosition
// }

Removal

// Remove a connector
connector.remove();

Example: Flowchart

// Create shapes
const start = app.diagramSystem.createShape('terminal', {
  position: new paper.Point(400, 100),
  label: 'Start'
});

const process = app.diagramSystem.createShape('process', {
  position: new paper.Point(400, 220),
  label: 'Process'
});

const decision = app.diagramSystem.createShape('decision', {
  position: new paper.Point(400, 360),
  label: 'OK?'
});

const end = app.diagramSystem.createShape('terminal', {
  position: new paper.Point(400, 500),
  label: 'End'
});

const retry = app.diagramSystem.createShape('process', {
  position: new paper.Point(600, 360),
  label: 'Retry'
});

// Connect with different styles
app.diagramSystem.connect(start, process, {
  headStyle: 'classic'
});

app.diagramSystem.connect(process, decision, {
  headStyle: 'classic'
});

app.diagramSystem.connect(decision, end, {
  headStyle: 'classic',
  label: 'Yes'
});

app.diagramSystem.connect(decision, retry, {
  headStyle: 'classic',
  label: 'No',
  lineColor: '#ef4444'
});

app.diagramSystem.connect(retry, process, {
  headStyle: 'classic',
  routing: 'orthogonal'
});