fabric.js 撤销、恢复和保存操作(上一步/下一步)

3,164 阅读2分钟

fabric.js 撤销、恢复和保存操作(上一步/下一步)

const state = {
    saveLen: 0,
    deleLen: 0,
    operIndex: -1
}
window.saveOperateList = []
window.deleteOperateList = []
const getters = {
    
}
const mutations = {
    // 操作保存的数据
    OPERATE_OPERATE_DATA (state) {
        const json = window.card.toDatalessJSON()
        if (state.deleLen > 0) {
            window.deleteOperateList.some(item => {
                window.saveOperateList[item].del = true
            })  
            window.saveOperateList = window.saveOperateList.filter(item => {
                return !item.del
            })
            window.deleteOperateList = []
            window.saveOperateList.push(json)
            state.operIndex = window.saveOperateList.length - 1
        } else {
            window.saveOperateList.push(json)
            state.operIndex += 1
        }
        state.saveLen = window.saveOperateList.length
        state.deleLen = window.deleteOperateList.length
    },
    // 上一步操作
    PREV_STEP_OPERATE (state) {
        if (state.operIndex > 0) {
            window.card.loadFromJSON(window.saveOperateList[state.operIndex - 1]).renderAll()
            if (window.deleteOperateList.includes(state.operIndex - 1)) {
            } else {
                window.deleteOperateList.push(state.operIndex)
                state.operIndex -= 1
            }
        }
        state.saveLen = window.saveOperateList.length
        state.deleLen = window.deleteOperateList.length
    },
    // 下一步操作
    NEXT_STEP_OPERATE (state) {
        if (state.operIndex + 1 >= window.saveOperateList.length) {
            return
        }
        window.card.loadFromJSON(window.saveOperateList[state.operIndex + 1]).renderAll()
        if (window.deleteOperateList.includes(state.operIndex + 1)) {
            const index = window.deleteOperateList.indexOf(state.operIndex + 1)
            window.deleteOperateList.splice(index, 1)
        } else {
        }
        state.operIndex = state.operIndex + 1
        state.saveLen = window.saveOperateList.length
        state.deleLen = window.deleteOperateList.length
    }
}
const actions = {
}
export default { state, getters, mutations, actions }

字段解释:

  • saveLen:保存每一步的数据 saveOperateList 的长度
  • deleLen:需要删除每一步的数据 deleteOperateList 的长度
  • operIndex:操作的 Index 的值
  • window.saveOperateList:保存的数据,存的值为每一步的 json 数据
  • window.deleteOperateList:需要删除每一步的数据列表,存的值为 saveOperateList 的每一步的 index 的值

思路:

  1. 保存操作记录:
    1. deleLen <= 0 即没有需要删除的操作记录
      1. 定义jsonconst json = window.card.toDatalessJSON()
      2. saveOperateList 中 push 数据:window.saveOperateList.push(json)
      3. operIndex的值往上加一:state.operIndex += 1
    2. deleLen > 0 的时候,即有删除操作记录的数据的时候
      1. 遍历deleteOperateList数组,给saveOperateList[item]每一个对象加一个del属性(需要删除掉的值)
      2. filter``saveOperateList数组,把有 del 属性的过滤掉
      3. deleteOperateList赋值为[]
      4. saveOperateList添加新的数据
      5. 设置 operIndex 的值
    3. 设置saveLendeleLen 的值
  2. 撤销/上一步操作:
    1. 如果operIndex > 0
      1. 加载上一次保存的数据:window.card.loadFromJSON(window.saveOperateList[state.operIndex - 1]).renderAll()
      2. 如果deleteOperateList包含当前operIndex - 1则不进任何操作,否则把operIndex pushdeleteOperateList
      3. 再把operIndex - 1
    2. 如果operIndex <= 0 不进行任何操作,说明此时不能进行撤销(上一步)操作
    3. 设置saveLendeleLen 的值
  3. 恢复/下一步操作:
    1. 如果operIndex + 1 > saveOperateList.length则不进行任何操作,说明此时不能进行恢复操作,直接return即可
    2. 加载 operIndex + 1 的数据:window.card.loadFromJSON(window.saveOperateList[state.operIndex + 1]).renderAll()
    3. 如果 deleteOperateList包含operIndex + 1的值,从deleteOperateList中删除这个值;如果不包含,则不删除
    4. 设置operIndex 的值
    5. 设置saveLendeleLen 的值

此时即完成了一个 保存数据、撤销、恢复整个流程

由于设置的 operIndex 为 -1 ,所以需要在 card 初始化时进行保存初始化的 json 数据,在初始化完成之后进行调用一次 OPERATE_OPERATE_DATA函数

后面每次进行操作的时候调用 OPERATE_OPERATE_DATA,每次点击撤销的时候调用PREV_STEP_OPERATE,点击恢复的时候调用NEXT_STEP_OPERATE