撤消Fabric.js的重做

gco*_*gco 15 javascript arrays fabricjs

我正在尝试为我的Fabric.js画布添加撤消/重做功能.我的想法是有一个计数器来计算画布修改(现在它计算对象的添加).我有一个状态数组,它将整个画布作为JSON推送到我的数组.

然后我只想回忆起各州

canvas.loadFromJSON(state[state.length - 1 + ctr],
Run Code Online (Sandbox Code Playgroud)

当用户点击undo时,ctr将减1并将状态加载到数组之外; 当用户点击重做时,ctr将增加1并将状态加载到数组之外.

当我用简单的数字体验这一点时,一切正常.使用真正的面料帆布,我遇到了一些麻烦 - >它不起作用.我认为这取决于我的事件处理程序

canvas.on({
   'object:added': countmods
});
Run Code Online (Sandbox Code Playgroud)

jsfiddle在这里:

这里是工作数字唯一的例子(结果见控制台):jsFiddle

gco*_*gco 20

我自己回答了这个问题.

jsfiddle:

我做了什么:

if (savehistory === true) {
    myjson = JSON.stringify(canvas);
    state.push(myjson);
} // this will save the history of all modifications into the state array, if enabled

if (mods < state.length) {
    canvas.clear().renderAll();
    canvas.loadFromJSON(state[state.length - 1 - mods - 1]);
    canvas.renderAll();
    mods += 1;
} // this will execute the undo and increase a modifications variable so we know where we are currently. Vice versa works the redo function.
Run Code Online (Sandbox Code Playgroud)

仍然需要改进来处理图纸和物体.但这应该很简单.


o0o*_*o0o 5

您可以使用类似diff-patch或 的东西tracking object version。首先,您监听所有对象更改:object:created, object:modified....,通过将 canvas.toObject() 保存在变量中来保存画布的第一个快照;下一次,运行diffpatcher .diff(snapshot,canvas.toObject()),并只保存补丁。要撤消,您可以使用 diffpatcher.reverse 这些补丁。要重做,只需使用函数 diffpatcher.patch。通过这种方式,您可以节省内存,但会增加 CPU 使用率。

使用fabricjs,您可以使用 Object#saveState() 并处理 object: added 以将原始状态保存到数组(用于撤消任务),监听 object:modified、object:removing(用于重做任务)。这种方式更轻量级,也很容易实现。更多最好通过使用循环队列来限制您的历史长度。