历史与连续编辑
示例函数接收已经创建的Editor,SkyNoteEditor类型从@skynote/editor导入。
撤销与重做
| 接口 | 返回值 / 含义 |
|---|---|
canUndo / canRedo | 当前是否可撤销或重做 |
undo() / redo() | boolean,是否成功执行 |
clearHistory() | 清空历史,加载初始示例或恢复本地文档后按需使用 |
onHistoryChange(listener) | 状态变化通知,返回解绑函数 |
getHistorySnapshot() | 完整历史快照,供显式检查点场景使用 |
视口、选区、工具和主题属于会话,不因这些操作创建文档历史。clearHistory()会移除回退能力,不能为了让工具栏变灰而随意调用。
一次动作包含多个命令
editor.engine.documentStore.batch(fn, labelOrOptions?)是公开的批量事务入口。第二个参数可为记录名称字符串,或{label?, groupId?};fn同步执行,批量创建与修改归为一次历史动作。
节点示例中的两个节点与连线在同一batch内创建。不要把异步请求放进batch里等待;先准备数据,再在同步事务中提交。业务前置条件也应先检查,不把batch当作可以随时回滚任意外部副作用的数据库事务。
连续取色或滑块
ts
export function recolorDuringGesture(
editor: SkyNoteEditor<HTMLElement>,
ids: string[],
colors: string[],
groupId: string
): void {
for (const fill of colors) editor.updateNodeStyle(ids, { fill }, { groupId, label: '调整配色' });
}同次用户交互传相同groupId,下一次交互生成新的ID。上例的数组只是模拟多次采样,实际面板应在每次输入时提交当前值,不需要收集全部拖动帧。
groupId用于合并相邻的同组修改,不是全局永久分组。不要把固定字符串反复用于多次独立操作,也不要在中间穿插无关命令后假定仍会合并。
行为一致的尺寸编辑
ts
export function resizeFromPanel(editor: SkyNoteEditor<HTMLElement>, ids: string[], groupId: string): () => void {
editor.setNodeSize(ids, { width: 240 }, { groupId, label: '调整节点尺寸' });
return () => editor.endGeometryEdit(groupId);
}setNodeSize和setNodeRotation会使用几何编辑会话保留交互快照,避免连续数值修改不断累积缩放误差。面板关闭、失焦或切换目标时,调用返回的结束函数;传入原来的groupId,旧面板不会结束另一组正在进行的编辑。
rotateNodesBy是绕整体中心的增量旋转;setNodeRotation是每个节点各自中心的绝对角度,二者不能混用来模拟同一种面板。
导入与恢复的历史差异
importDocument是可撤销的一次内容替换。restoreDocument用于已校验的本地恢复,不进撤销栈,并清空原历史。restoreRecovery显式恢复文档和历史检查点,需要同时检查其返回结果。
保存普通JSON快照不会同时保存撤销重做栈。接口与失败行为见文档API。