撤销和重做
撤销/重做系统 - 跟踪和恢复图修改
撤销/重做功能
功能概述
本示例演示图操作的撤销/重做功能实现。每次修改(添加节点、删除节点、移动节点、添加连线、删除连线)都记录在历史堆栈中,允许用户恢复或重放更改。
核心特性实现
历史堆栈管理
interface GraphAction {
type: 'addNode' | 'removeNode' | 'moveNode' | 'addLine' | 'removeLine';
data: any;
timestamp: number;
}
const historyRef = useRef<GraphAction[]>([]);
const historyIndexRef = useRef(-1);
const recordAction = (action: GraphAction) => {
// 如果不在末尾,删除任何未来历史
historyRef.current = historyRef.current.slice(0, historyIndexRef.current + 1);
historyRef.current.push(action);
historyIndexRef.current++;
};
操作包装器
const addNodeWithUndo = async (node: JsonNode) => {
await graphInstance.addNodes([node]);
recordAction({
type: 'addNode',
data: { node },
timestamp: Date.now()
});
};
const removeNodeWithUndo = async (nodeId: string) => {
const node = graphInstance.getNodeById(nodeId);
await graphInstance.removeNodeById(nodeId);
recordAction({
type: 'removeNode',
data: { node },
timestamp: Date.now()
});
};
撤销/重做实现
const undo = async () => {
if (historyIndexRef.current < 0) return;
const action = historyRef.current[historyIndexRef.current];
switch (action.type) {
case 'addNode':
await graphInstance.removeNodeById(action.data.node.id);
break;
case 'removeNode':
await graphInstance.addNodes([action.data.node]);
break;
case 'moveNode':
await graphInstance.updateNode(action.data.node.id, {
x: action.data.oldX,
y: action.data.oldY
});
break;
}
historyIndexRef.current--;
};
const redo = async () => {
if (historyIndexRef.current >= historyRef.current.length - 1) return;
historyIndexRef.current++;
const action = historyRef.current[historyIndexRef.current];
// 重放操作...
};
创意使用场景
图编辑器:允许用户自由实验并恢复错误。
协作编辑:跟踪更改以解决冲突。
分步教程:指导用户完成图构建。
错误恢复:防止意外删除或修改。
动画录制:记录和重放图创建过程。