跳到主要内容

Commands API

AgileJS 提供了丰富的内置命令类,涵盖节点、边、分组等各类操作。所有命令都实现 ICommand 接口,支持撤销/重做。

节点命令

AddNodeCommand

添加节点。

class AddNodeCommand implements ICommand {
constructor(graph: Graph, node: NodeData)
}

示例:

engine.history.execute(
new AddNodeCommand(engine.graph, {
id: 'node-1',
shape: 'rect',
position: { x: 100, y: 100 },
size: { width: 120, height: 80 }
})
);

RemoveNodeCommand

删除节点及其相关边。

class RemoveNodeCommand implements ICommand {
constructor(graph: Graph, nodeId: string)
}

示例:

engine.history.execute(
new RemoveNodeCommand(engine.graph, 'node-1')
);

MoveNodeCommand

移动单个节点到指定位置。

提示

移动节点场景历史记录管理时,因为移动过程状态不需要关心,建议采用合并方式提高性能。

class MoveNodeCommand implements ICommand {
constructor(
graph: Graph,
nodeId: string,
nextX: number,
nextY: number
)
}

示例:

// 支持命令合并(拖动时使用)
engine.history.execute(
new MoveNodeCommand(engine.graph, 'node-1', 200, 150),
{ merge: true, mergeKey: 'move-node-1' }
);

MoveNodesCommand

批量移动多个节点(相对偏移)。

class MoveNodesCommand implements ICommand {
constructor(
graph: Graph,
nodeIds: string[],
dx: number,
dy: number
)
}

示例:

const selectedNodes = engine.graph.getNodes()
.filter(n => n.selected)
.map(n => n.id);

engine.history.execute(
new MoveNodesCommand(engine.graph, selectedNodes, 50, 30)
);

ResizeNodeCommand

调整节点尺寸。

class ResizeNodeCommand implements ICommand {
constructor(
graph: Graph,
nodeId: string,
width: number,
height: number
)
}

示例:

engine.history.execute(
new ResizeNodeCommand(engine.graph, 'node-1', 150, 100)
);

ResizeNodeWithPortsCommand

调整节点尺寸,同时等比缩放锚点偏移。

class ResizeNodeWithPortsCommand implements ICommand {
constructor(
graph: Graph,
nodeId: string,
width: number,
height: number
)
}

示例:

// 适用于有锚点的节点
engine.history.execute(
new ResizeNodeWithPortsCommand(engine.graph, 'node-1', 200, 120)
);

SetNodeRotationCommand

设置节点旋转角度。

class SetNodeRotationCommand implements ICommand {
constructor(
graph: Graph,
nodeId: string,
rotation: number // 弧度
)
}

示例:

engine.history.execute(
new SetNodeRotationCommand(engine.graph, 'node-1', Math.PI / 4)
);

SetZIndexCommand

设置节点层级。

class SetZIndexCommand implements ICommand {
constructor(
graph: Graph,
nodeId: string,
zIndex: number
)
}

示例:

// 置顶节点
const maxZ = Math.max(
...engine.graph.getNodes().map(n => n.zIndex ?? 0)
);
engine.history.execute(
new SetZIndexCommand(engine.graph, 'node-1', maxZ + 1)
);

UpdateNodeDataCommand

更新节点的 data 属性(部分更新)。

class UpdateNodeDataCommand implements ICommand {
constructor(
graph: Graph,
nodeId: string,
data: Record<string, unknown>
)
}

示例:

engine.history.execute(
new UpdateNodeDataCommand(engine.graph, 'node-1', {
style: {
fill: '#4CAF50',
stroke: '#2E7D32'
}
})
);

UpdateNodePropsCommand

更新节点的基础属性(selectabledraggablegroupId)。

class UpdateNodePropsCommand implements ICommand {
constructor(
graph: Graph,
nodeId: string,
props: {
selectable?: boolean;
draggable?: boolean;
groupId?: string;
}
)
}

示例:

engine.history.execute(
new UpdateNodePropsCommand(engine.graph, 'node-1', {
selectable: false,
draggable: false
})
);

边命令

AddEdgeCommand

添加边。

class AddEdgeCommand implements ICommand {
constructor(graph: Graph, edge: EdgeData)
}

示例:

engine.history.execute(
new AddEdgeCommand(engine.graph, {
id: 'edge-1',
shape: 'edge-straight',
source: 'node-1',
target: 'node-2'
})
);

RemoveEdgeCommand

删除边。

class RemoveEdgeCommand implements ICommand {
constructor(graph: Graph, edgeId: string)
}

示例:

engine.history.execute(
new RemoveEdgeCommand(engine.graph, 'edge-1')
);

UpdateEdgeDataCommand

更新边的 data 属性。

class UpdateEdgeDataCommand implements ICommand {
constructor(
graph: Graph,
edgeId: string,
data: Record<string, unknown>
)
}

示例:

engine.history.execute(
new UpdateEdgeDataCommand(engine.graph, 'edge-1', {
style: {
stroke: '#f44336',
lineWidth: 3
}
})
);

SetEdgeShapeCommand

切换边的形状类型。

class SetEdgeShapeCommand implements ICommand {
constructor(
graph: Graph,
edgeId: string,
shape: string
)
}

示例:

// 切换为贝塞尔曲线
engine.history.execute(
new SetEdgeShapeCommand(engine.graph, 'edge-1', 'edge-bezier')
);

SetEdgePointsCommand

设置边的控制点(用于折线等)。

class SetEdgePointsCommand implements ICommand {
constructor(
graph: Graph,
edgeId: string,
prevPoints: Point[] | undefined,
nextPoints: Point[] | undefined
)
}

示例:

const edge = engine.graph.getEdge('edge-1');
const prevPoints = edge?.points;
const nextPoints = [
{ x: 100, y: 100 },
{ x: 150, y: 150 },
{ x: 200, y: 100 }
];

engine.history.execute(
new SetEdgePointsCommand(engine.graph, 'edge-1', prevPoints, nextPoints)
);

ReconnectEdgeCommand

重新连接边(更改源/目标节点或锚点)。

class ReconnectEdgeCommand implements ICommand {
constructor(
graph: Graph,
edgeId: string,
prev: {
source: string;
target: string;
sourcePortId?: string;
targetPortId?: string;
},
next: {
source: string;
target: string;
sourcePortId?: string;
targetPortId?: string;
}
)
}

示例:

const edge = engine.graph.getEdge('edge-1')!;
const prev = {
source: edge.source,
target: edge.target,
sourcePortId: edge.sourcePortId,
targetPortId: edge.targetPortId
};
const next = {
source: 'node-3',
target: 'node-2',
sourcePortId: 'port-1',
targetPortId: 'port-2'
};

engine.history.execute(
new ReconnectEdgeCommand(engine.graph, 'edge-1', prev, next)
);

层级命令

ReorderZIndexCommand

批量重排所有节点的 zIndex。

class ReorderZIndexCommand implements ICommand {
constructor(graph: Graph, nextOrder: string[])
}

示例:

const newOrder = ['node-3', 'node-1', 'node-2'];
engine.history.execute(
new ReorderZIndexCommand(engine.graph, newOrder)
);

层级辅助函数

提示

提供常用的置顶 bringNodesToFront 、置底 sendNodesToBack 、上移一层 moveNodesUp 、下移一层 moveNodesDown 操作,通常用于编辑器场景。

以下函数提供便捷的层级操作,内部使用 ReorderZIndexCommand

bringNodesToFront()

将节点置顶。

function bringNodesToFront(
graph: Graph,
nodeIds: string[],
history?: CommandHistory
): void

示例:

const selectedIds = engine.graph.getNodes()
.filter(n => n.selected)
.map(n => n.id);

bringNodesToFront(engine.graph, selectedIds, engine.history);

sendNodesToBack()

将节点置底。

function sendNodesToBack(
graph: Graph,
nodeIds: string[],
history?: CommandHistory
): void

moveNodesUp()

将节点上移一层。

function moveNodesUp(
graph: Graph,
nodeIds: string[],
history?: CommandHistory
): void

moveNodesDown()

将节点下移一层。

function moveNodesDown(
graph: Graph,
nodeIds: string[],
history?: CommandHistory
): void

分组命令

GroupNodesCommand

创建分组(支持嵌套)。

class GroupNodesCommand implements ICommand {
constructor(
graph: Graph,
nodeIds: string[],
groupId: string
)
}

示例:

const selectedIds = engine.graph.getNodes()
.filter(n => n.selected)
.map(n => n.id);

engine.history.execute(
new GroupNodesCommand(engine.graph, selectedIds, 'group-1')
);

UngroupNodesCommand

解散分组(逐层解组或完全展平)。

class UngroupNodesCommand implements ICommand {
constructor(
graph: Graph,
nodeIds: string[],
options?: { flattenAll?: boolean }
)
}

示例:

// 解散最内层组
engine.history.execute(
new UngroupNodesCommand(engine.graph, groupedNodeIds)
);

// 完全展平所有层级
engine.history.execute(
new UngroupNodesCommand(engine.graph, groupedNodeIds, { flattenAll: true })
);

变换命令

GroupTransformCommand

批量变换节点(位置、尺寸、旋转、锚点)。

class GroupTransformCommand implements ICommand {
constructor(
graph: Graph,
updates: Array<{
id: string;
prev: {
position: Point;
size: Size;
rotation: number;
ports?: Record<string, Point>;
};
next: {
position: Point;
size: Size;
rotation: number;
ports?: Record<string, Point>;
};
}>
)
}

示例:

const updates = selectedNodes.map(node => ({
id: node.id,
prev: {
position: { ...node.position },
size: { ...node.size },
rotation: node.rotation ?? 0
},
next: {
position: { x: node.position.x + 10, y: node.position.y + 10 },
size: { width: node.size.width * 1.1, height: node.size.height * 1.1 },
rotation: (node.rotation ?? 0) + 0.1
}
}));

engine.history.execute(
new GroupTransformCommand(engine.graph, updates)
);

画布命令

SetCanvasBackgroundCommand

设置画布背景色。

class SetCanvasBackgroundCommand implements ICommand {
constructor(
engine: CanvasEngine,
nextBackground: string
)
}

示例:

engine.history.execute(
new SetCanvasBackgroundCommand(engine, '#f5f5f5')
);

SetGridOptionsCommand

设置网格插件选项。

class SetGridOptionsCommand implements ICommand {
constructor(
engine: CanvasEngine,
nextOptions: { size?: number; color?: string; alpha?: number }
)
}

示例:

engine.history.execute(
new SetGridOptionsCommand(engine, {
size: 25,
color: '#e0e0e0',
alpha: 0.3
})
);

SetGuidesOptionsCommand

设置参考线插件选项。

class SetGuidesOptionsCommand implements ICommand {
constructor(
engine: CanvasEngine,
nextOptions: {
threshold?: number;
color?: string;
lineWidth?: number;
lineDash?: number[];
}
)
}

UpdateNodePortsCommand

更新节点的锚点列表。

class UpdateNodePortsCommand implements ICommand {
constructor(
graph: Graph,
nodeId: string,
nextPorts: PortData[]
)
}

使用技巧

1. 命令合并

频繁操作应启用合并:

function onNodeDrag(nodeId: string, x: number, y: number) {
engine.history.execute(
new MoveNodeCommand(engine.graph, nodeId, x, y),
{
merge: true,
mergeKey: `move-${nodeId}`,
mergeWindowMs: 500
}
);
}

2. 批量操作使用事务

engine.history.beginTransaction('Delete Selection');

try {
selectedEdges.forEach(edge => {
engine.history.execute(new RemoveEdgeCommand(engine.graph, edge.id));
});
selectedNodes.forEach(node => {
engine.history.execute(new RemoveNodeCommand(engine.graph, node.id));
});

engine.history.commitTransaction();
} catch (error) {
engine.history.rollbackTransaction();
}

3. 自定义命令

class MyCustomCommand implements ICommand {
label = 'My Custom Operation';

constructor(private graph: Graph, private data: any) {}

do(): void {
// 执行逻辑
this.graph.markDirty();
}

undo(): void {
// 撤销逻辑
this.graph.markDirty();
}

debugInfo(): CommandDebugInfo {
return {
nodes: ['node-1'],
changes: [{
entity: 'node',
id: 'node-1',
path: 'custom',
prev: 'old',
next: 'new'
}]
};
}
}

命令列表总览

命令用途支持合并
AddNodeCommand添加节点
RemoveNodeCommand删除节点
MoveNodeCommand移动节点
MoveNodesCommand批量移动
ResizeNodeCommand调整尺寸
ResizeNodeWithPortsCommand调整尺寸(含锚点)
SetNodeRotationCommand旋转节点
SetZIndexCommand设置层级
UpdateNodeDataCommand更新数据
UpdateNodePropsCommand更新属性
AddEdgeCommand添加边
RemoveEdgeCommand删除边
UpdateEdgeDataCommand更新边数据
SetEdgeShapeCommand切换边类型
SetEdgePointsCommand设置控制点
ReconnectEdgeCommand重连边
ReorderZIndexCommand重排层级
GroupNodesCommand创建分组
UngroupNodesCommand解散分组
GroupTransformCommand批量变换
SetCanvasBackgroundCommand设置背景
SetGridOptionsCommand设置网格
SetGuidesOptionsCommand设置参考线
UpdateNodePortsCommand更新锚点