Ports
Ports are connection points on items where connectors attach. The Port Manager handles port creation, positioning, and visual display.
Overview
Ports are stored as lightweight data on items (item.data.ports) rather than as separate objects. Visual indicators are created on-demand only when needed (during connect mode).
Adding Ports
Standard Ports (4-way)
Most shapes use standard ports at top, bottom, left, and right:
// Add standard 4-port configuration
app.diagramSystem.addPorts(item, 'standard');
// Or explicitly
app.diagramSystem.portManager.addStandardPorts(item);
Line Ports (Start/End)
For paths and lines, use start/end ports:
app.diagramSystem.portManager.addLinePorts(item);
// Creates ports at: 'start' and 'end' positions
Path Ports
For closed freehand paths, distribute ports along the path:
app.diagramSystem.portManager.addPathPorts(item, 4);
// Creates 4 ports evenly distributed along the path
Custom Ports
Add ports at specific positions:
app.diagramSystem.portManager.addPorts(item, [
{ position: 'top', type: 'output' },
{ position: 'bottom', type: 'input' },
{ position: 'left', type: 'both' },
{ position: 'right', type: 'both' },
{ position: 'center', type: 'both' }
]);
Port Positions
| Position | Description |
|---|---|
top |
Center of top edge |
bottom |
Center of bottom edge |
left |
Center of left edge |
right |
Center of right edge |
top-left |
Top-left corner |
top-right |
Top-right corner |
bottom-left |
Bottom-left corner |
bottom-right |
Bottom-right corner |
center |
Center of bounds |
start |
First point (for paths) |
end |
Last point (for paths) |
custom |
Custom position with offset |
Port Types
Control which direction connections can flow:
| Type | Description |
|---|---|
input |
Only accepts incoming connections |
output |
Only provides outgoing connections |
both |
Accepts both directions (default) |
app.diagramSystem.portManager.addPorts(item, [
{ position: 'top', type: 'input' }, // Only incoming
{ position: 'bottom', type: 'output' } // Only outgoing
]);
Getting Ports
// Get all ports for an item
const ports = app.diagramSystem.getPorts(item);
// Get a specific port by position
const topPort = app.diagramSystem.portManager.getPort(item, 'top');
// Get port position (absolute coordinates)
const position = app.diagramSystem.portManager.getPortPosition(item, topPort);
Port Detection
Find ports near a point (for snapping):
// Find nearest port within snap distance
const nearest = app.diagramSystem.portManager.findNearestPort(point, {
snapDistance: 25, // Default: 25px
excludeItem: sourceItem, // Exclude an item
excludePort: sourcePort, // Exclude a specific port
connectionType: 'output' // Filter by type
});
if (nearest) {
console.log('Found port:', nearest.portData);
console.log('On item:', nearest.item);
console.log('At position:', nearest.position);
console.log('Distance:', nearest.distance);
}
// Find port exactly at a point (for click detection)
const port = app.diagramSystem.portManager.findPortAt(point, 12);
Port Visuals
Port visuals are temporary circles shown during connect mode:
// Show port visuals for all items (called when entering connect mode)
app.diagramSystem.portManager.showAllPortVisuals();
// Hide all port visuals
app.diagramSystem.portManager.hideAllPortVisuals();
// Update visual positions (after items move)
app.diagramSystem.portManager.updateVisualPositions();
Visual Configuration
// Default visual config
{
radius: 8, // Port circle size
strokeColor: '#3b82f6', // Blue outline
strokeWidth: 2,
dashArray: [3, 3], // Dotted outline
fillColor: 'transparent', // Default fill
hoverFill: 'rgba(59, 130, 246, 0.2)', // On hover
highlightFill: 'rgba(251, 191, 36, 0.3)', // When snapped
connectedFill: 'rgba(16, 185, 129, 0.2)', // When connected
snapDistance: 25 // Snap detection radius
}
Port Highlighting
Visual feedback during connection:
// Highlight a port (when snapping to it)
app.diagramSystem.portManager.highlightPort(portData, item, true);
// Remove highlight
app.diagramSystem.portManager.highlightPort(portData, item, false);
// Clear all highlights
app.diagramSystem.portManager.clearHighlights();
Removing Ports
// Remove all ports from an item
app.diagramSystem.portManager.removePorts(item);
Port Data Structure
Ports are stored on item.data.ports as an array:
item.data.ports = [
{
id: 'item_123_top_0', // Unique ID
position: 'top', // Position type
type: 'both', // Connection type
maxConnections: Infinity, // Max connections allowed
offset: { x: 0, y: 0 }, // Custom offset
param: undefined // For path ports: t value (0-1)
},
// ... more ports
];
item.data.hasPorts = true; // Flag indicating ports exist
Automatic Port Assignment
When diagram mode is active, ports are automatically added:
- Diagram shapes - Standard 4-port on creation
- Open paths - Start/end ports
- Closed paths - Path-distributed ports
- Other items - Standard 4-port when entering connect mode
// Auto-assignment happens when:
// 1. Creating a shape via app.diagramSystem.createShape()
// 2. Entering connect mode with items that don't have ports
Direction Vectors
Get the outward direction for routing:
const direction = app.diagramSystem.portManager.getPortDirection('top');
// Returns: paper.Point(0, -1) // Pointing up
// Direction vectors:
// top: (0, -1)
// bottom: (0, 1)
// left: (-1, 0)
// right: (1, 0)
// top-left: (-0.707, -0.707)
// top-right: (0.707, -0.707)
// bottom-left: (-0.707, 0.707)
// bottom-right: (0.707, 0.707)
Integration with Connectors
When creating connectors, ports are automatically used:
// Automatic port selection
app.diagramSystem.connect(itemA, itemB);
// Finds best ports based on relative positions
// Manual port selection
const portA = app.diagramSystem.portManager.getPort(itemA, 'bottom');
const portB = app.diagramSystem.portManager.getPort(itemB, 'top');
app.diagramSystem.connectPorts(portA, portB);