fabric 撤销保存重做 队列+指针
画布上的 操作,撤销保存重做是少不了的,记录下实现:(项目中的撤销重做逻辑)
1、主要逻辑就是一个数组 operateList 保存所有步骤
2、每次 增删改 操作,都会将当前画布序列化,并插入当前指针 +1 项,这是防止后续可能存在步骤(而不能简单的 push 在队尾)
3、撤销,判断前一针是否有值,有值则进行反序列化,并改变指针位置 -1
4、下一步,判断后一针是否有值,有值则进行反序列化,更新指针位置 +1
5、队列长度,限制保存步数,内存有限;保存时判断是否数组过长,超长则队列从头出一个,更新指针位置 -1
代码:
import { fabric } from 'fabric';
import { Rect } from "./rect";
import { KeyCode } from "./key-code";
/**
* 保存上一步下一步
* 序列化,反序列化
*/
export class ActionBackNext {
state = {
// 指针标记当前位置
pointer: -1,
// 操作记录
operateList: [],
// 深度,记录步骤次数
// deep: 20,
}
constructor(canvas) {
// 保存 canvas 对象
this.state['canvas'] = canvas;
// 绑定键盘事件
this.bindKeyBoard(canvas);
let rect = new fabric.Rect(Rect.defaultRect());
canvas.add(rect);
// 添加也要保存
this.operateData();
}
/**
* 绑定键盘事件
* @param canvas
*/
bindKeyBoard(canvas) {
$(document).on('keydown', (e) => {
const key = e.originalEvent.keyCode;
switch (key) {
// case KeyCode.Q: // 保存
// console.log('save');
// this.operateData();
// break;
case KeyCode.W: // 上一步
console.log('back');
this.prevStepOperate();
break;
case KeyCode.E: // 下一步
console.log('next');
this.nextStepOperate();
break;
}
});
canvas.on('object:modified', (e) => {
// 为了方便保存,调整图形直接触发保存
this.operateData();
console.log('save');
});
}
/**
* 操作保存的数据
*/
operateData = () => {
const { canvas, operateList, pointer, deep } = this.state;
let max = deep;
let list = [ ...operateList ];
// 当前状态
let currentPointer = pointer;
const json = canvas.toJSON();
// 更新指针位置
currentPointer += 1;
// 考虑到可能存在后续动作,插入队列操作
list.splice(currentPointer, 0, json);
if (max && max < list.length) {
// 深度存在,则判断当前队列长,超出则从头移出队列
list.shift();
currentPointer -= 1;
}
// 保存数据
this.setState({
operateList: list,
pointer: currentPointer,
});
}
/**
* 合并更新
* @param obj
*/
setState(obj) {
this.state = Object.assign(this.state, obj);
}
/**
* 上一步
*/
prevStepOperate = () => {
const { canvas, operateList, pointer } = this.state;
let list = [ ...operateList ];
let currentPointer = pointer;
if (currentPointer > 0) {
// 加载前一步
currentPointer -= 1;
canvas.loadFromJSON(list[currentPointer]).renderAll();
}
this.setState({
operateList: [ ...list ],
pointer: currentPointer
})
}
/**
* 下一步
*/
nextStepOperate = () => {
const { canvas, operateList, pointer } = this.state;
let list = [ ...operateList ];
let currentPointer = pointer;
// 指针移动
currentPointer += 1;
if (currentPointer >= list.length) {
return;
}
canvas.loadFromJSON(list[currentPointer]).renderAll();
this.setState({
operateList: [ ...list ],
pointer: currentPointer
});
}
}

浙公网安备 33010602011771号