Install @playcanvas/pcui-graph via npm
mainTo add PCUI Graph to your project, install the package using npm:
npm install @playcanvas/pcui-graphrepository·main·Indexed 41 days ago
https://github.com/playcanvas/pcui-graphA PCUI plugin for creating node-based visual graphs in the browser. It supports undirected, directed, and visual scripting graphs with input/output ports, and allows graphs to be serialized to and from JSON. Version 5.2.5.
To add PCUI Graph to your project, install the package using npm:
npm install @playcanvas/pcui-graphIf you are developing on the PCUI Graph repository, use the following commands:
npm run build: Generates a production build including UMD, ESM, TypeScript types, and styles.npm run lint: Runs ESLint and Stylelint.npm run watch: Starts a watch mode for incremental rebuilds.npm run docs: Builds the API reference documentation into the docs folder.npm run build # Production build (UMD + ESM + types + styles)
npm run lint # Run ESLint and Stylelint
npm run watch # Watch mode with incremental rebuilds
npm run docs # Build API referenceAfter installation, import the Graph class along with the required PCUI and PCUI Graph styles. You can instantiate a graph by passing a schema object that defines nodes and edges.
Each node in the schema can have properties like name and fill. Edges define connections between nodes using from and to arrays (specifying node types or IDs) and can include styling like stroke. Once instantiated, append graph.dom to your document to render the graph view.
import Graph from '@playcanvas/pcui-graph';
import '@playcanvas/pcui/styles';
import '@playcanvas/pcui-graph/styles';
const schema = {
nodes: {
0: {
name: 'Hello',
fill: 'red'
},
1: {
name: 'World',
fill: 'green'
}
},
edges: {
0: {
from: [0], // this edge can connect nodes of type 0
to: [1], // to nodes of type 1
stroke: 'blue'
}
}
};
const graph = new Graph(schema);
document.body.appendChild(graph.dom);To explore graph examples and use Storybook as a local development environment, run:
npm install
npm run storybookThis will automatically open the Storybook interface in a new browser tab.
When multiple links (siblings) exist between the same two nodes, they can overlap. JointGraph provides an adjustVertices method to automatically calculate perpendicular offsets for these links, spreading them out symmetrically.
To enable this behavior, you must set adjustVertices: true in your GraphConfig. Once enabled, the graph listens for cell additions, removals, and changes to sources or targets to trigger the adjustment logic. You can also manually call adjustVertices(graph, cell) if needed.
How it works:
GAP (20px).The JointGraph implements a strict validateConnection logic to ensure valid graph topology. Connections are rejected if:
port attribute.in port cannot connect to another in port.out port cannot connect to another out port.in port that is already connected (and not hidden) cannot accept another connection.edge-type (or edgeType) attribute of the source magnet must match the target magnet.The Graph class is the primary entry point for creating node-based graphs. It extends the PCUI Element class. To instantiate a graph, you must provide a GraphSchema (defining the structure of nodes and edges) and an optional GraphOptions object.
| Option | Type | Default | Description |
|---|---|---|---|
initialData | GraphData | {} | The initial nodes and edges to populate the graph. |
dom | HTMLElement | undefined | The DOM element to which the graph will be attached. |
contextMenuItems | ContextMenuItem[] | [] | Custom menu items for the graph canvas. |
readOnly | boolean | false | If true, the graph is non-interactive and uses selfContainedMode. |
passiveUIEvents | boolean | false | If true, the graph won't automatically update data/view on interaction; you must handle events explicitly. |
incrementNodeNames | boolean | false | If true, automatically increments names for duplicate node names. |
restrictTranslate | boolean | false | Restricts graph translation to the graph area. |
edgeHoverEffect | boolean | true | Enables highlighting edges on hover. |
defaultStyles | Partial<DefaultStyles> | DEFAULT_CONFIG.defaultStyles | Overrides default styling for background, node, and edge. |
adjustVertices | boolean | undefined | If true, multiple edges between the same two nodes are spaced apart. |
import Graph from '@playcanvas/pcui-graph';
const schema = {
nodes: {
'myNodeType': {
attributes: [{ name: 'label', defaultValue: 'New Node' }]
}
},
edges: {
'myEdgeType': {
from: ['myNodeType'],
to: ['myNodeType']
}
}
};
const graph = new Graph(schema, {
readOnly: false,
edgeHoverEffect: true,
initialData: {
nodes: {
'node1': { id: 'node1', nodeType: 'myNodeType', posX: 100, posY: 100, attributes: { label: 'First' } }
},
edges: {}
}
});
document.body.appendChild(graph.dom);The DEFAULT_CONFIG object provides the baseline configuration for the graph, including behavior flags and visual styling for nodes and edges. You can override these values when initializing your graph instance.
readOnly: If true, prevents user interactions that modify the graph.passiveUIEvents: Controls how UI events are handled.incrementNodeNames: If true, automatically increments names when adding nodes.restrictTranslate: Restricts translation capabilities.edgeHoverEffect: Enables/disables visual feedback when hovering over edges.includeFonts: Whether to include custom fonts.useGlobalPCUI: Determines if the graph should use the global PCUI instance.adjustVertices: Controls vertex adjustment behavior.The defaultStyles object defines the visual properties for the graph background, nodes, and edges. Key properties include:
fill, fillSecondary, stroke, strokeSelected, strokeHover: Color properties for the node body and borders.textColor, textColorSecondary: Colors for text elements.baseHeight, baseWidth: Default dimensions for nodes.icon, iconColor: Icon configuration.stroke, strokeSelected: Color of the edge line.strokeWidth, strokeWidthSelected: Thickness of the edge line.targetMarker: Boolean to show/hide markers at the edge end.connectionStyle: The visual style of the connection (e.g., 'default').export const DEFAULT_CONFIG = {
readOnly: false,
passiveUIEvents: false,
incrementNodeNames: false,
restrictTranslate: false,
edgeHoverEffect: true,
includeFonts: true,
useGlobalPCUI: false,
adjustVertices: false,
defaultStyles: {
initialScale: 1,
initialPosition: {
x: 0,
y: 0
},
background: {
color: '#20292B',
gridSize: 10
},
node: {
fill: '#2c393c',
fillSecondary: '#364346',
stroke: '#293538',
strokeSelected: '#F60',
strokeHover: 'rgba(255, 102, 0, 0.32)',
textColor: '#FFFFFF',
textColorSecondary: '#b1b8ba',
includeIcon: true,
icon: '',
iconColor: '#F60',
baseHeight: 28,
baseWidth: 226,
textAlignMiddle: false,
lineHeight: 12
},
edge: {
stroke: 'rgb(3, 121, 238)',
strokeSelected: '#F60',
strokeWidth: 2,
strokeWidthSelected: 2,
targetMarker: true,
connectionStyle: 'default'
}
}
};The GraphConfig object allows you to customize the behavior and appearance of the graph. While the full type definition is in ./types, the following keys are used by the JointGraph constructor:
readOnly (boolean): If true, the graph becomes non-interactive.restrictTranslate (boolean): Controls whether translation is restricted.minZoom (number): The minimum zoom level allowed (default: 0.25).maxZoom (number): The maximum zoom level allowed (default: 1.5).adjustVertices (boolean): If true, the graph automatically calculates vertex offsets for sibling links to prevent them from overlapping.defaultStyles (object): Defines the initial visual state:background.color: The background color of the paper.background.gridSize: The size of the background grid.You can attach custom context menus to the canvas, individual nodes, or individual edges.
addCanvasContextMenu(items): Adds a menu that appears when clicking on the empty graph background.addNodeContextMenu(id, items): Adds a menu to a specific node.addEdgeContextMenu(id, items): Adds a menu to a specific edge.items is an array of ContextMenuItem objects.
Use GraphView to programmatically add, remove, and update nodes within the graph. When adding a node, you must provide data, a schema, and callbacks for edge creation and node selection.
To optimize performance when adding multiple nodes at once, use batchCells() before adding nodes and applyBatchedCells() once finished. This prevents unnecessary re-renders.
Common node operations include:
addNode(...): Creates a new node.removeNode(modelId): Removes a node by its model ID.updateNodeAttribute(id, attribute, value): Updates a specific attribute on a node.setNodeAttributeErrorState(id, attribute, value): Sets the error state for a node attribute.updateNodePosition(id, pos): Moves a node to a new { x, y } position.updateNodeType(id, nodeType): Changes the type of a node.selectNode(id) / deselectNode(id): Controls the selection state of a node.// Adding a node with batching for performance
graphView.batchCells();
graphView.addNode(
{ id: 'node-1', type: 'default' }, // NodeData
nodeSchema, // NodeSchema
(edgeId, edgeData) => { // onCreateEdge callback
console.log('Edge created:', edgeId);
},
(nodeData) => { // onNodeSelected callback
console.log('Node selected:', nodeData.id);
}
);
graphView.applyBatchedCells();The Graph class uses DOM-based events to communicate changes. You can listen to these events using the .on() method. Note that if readOnly is enabled, most interaction events are suppressed.
Events are dispatched using the GRAPH_ACTIONS constants. Common events include:
ADD_NODE: Fired when a node is added.DELETE_NODE: Fired when a node is deleted.SELECT_NODE: Fired when a node is selected.UPDATE_NODE_POSITION: Fired when a node is moved.UPDATE_NODE_ATTRIBUTE: Fired when a node attribute changes.ADD_EDGE: Fired when an edge is created.DELETE_EDGE: Fired when an edge is removed.SELECT_EDGE: Fired when an edge is selected.DESELECT_ITEM: Fired when selection is cleared.graph.on('EVENT_SELECT_NODE', ({ node, prevItem }) => {
console.log('Selected node:', node.id);
console.log('Previous item:', prevItem);
});