【问题标题】:How to do undo redo in fabric js using enlivenObjects如何使用enlivenObjects在fabric js中撤消重做
【发布时间】:2019-01-07 05:50:27
【问题描述】:

撤消重做功能适用于这段代码,但如何使用fabricjs enlivenObjects方法做同样的事情。我希望使用enlivenObjects而不是使用loadFromJSON方法来实现相同的结果。画布对象容器中的对象应该能够撤消和重做。

<input type="button" value="addrect" onclick="addrect()">
<input type="button" value="undo" onclick="undo()">
<input type="button" value="redo" onclick="redo()">
<input type="button" value="clear" onclick="clearcan()">
<br/>
<canvas id="fabriccanvas" width="600" height="200" style="border:1px solid #ccc"></canvas>

var canvas = new fabric.Canvas('fabriccanvas');
canvas.counter = 0;
var newleft = 0;
canvas.selection = false;

addrect = function addrect(top, left, width, height, fill) {
    canvas.add(new fabric.Rect({
        top: document.getElementById("fabriccanvas").height,
        name: 'rectangle ' + window.counter,
        left: 0 + newleft,
        width: 100,
        height: 100,
        fill: '#' + (0x1000000 + (Math.random()) * 0xffffff).toString(16).substr(1, 6),
        //fix attributes applied for all rects
        opacity: 0.75,
        lockRotation: true,
        originX: 'left',
        originY: 'bottom',
        cornerSize: 15,
        hasRotatingPoint: false,
        perPixelTargetFind: true,
        minScaleLimit: 1
    }));
    updateModifications(true);
    canvas.counter++;
    newleft += 100;
}
var state = [];
var mods = 0;
canvas.on(
    'object:modified', function () {
    updateModifications(true);
},
    'object:added', function () {
    updateModifications(true);
});

function updateModifications(savehistory) {
    if (savehistory === true) {
        myjson = JSON.stringify(canvas);
        state.push(myjson);
    }
}

undo = function undo() {
    if (mods < state.length) {
        canvas.clear().renderAll();
        canvas.loadFromJSON(state[state.length - 1 - mods - 1]);
        canvas.renderAll();
        //console.log("geladen " + (state.length-1-mods-1));
        //console.log("state " + state.length);
        mods += 1;
        //console.log("mods " + mods);
    }
}

redo = function redo() {
    if (mods > 0) {
        canvas.clear().renderAll();
        canvas.loadFromJSON(state[state.length - 1 - mods + 1]);
        canvas.renderAll();
        //console.log("geladen " + (state.length-1-mods+1));
        mods -= 1;
        //console.log("state " + state.length);
        //console.log("mods " + mods);
    }
}
clearcan = function clearcan() {
    canvas.clear().renderAll();
    newleft = 0;
}

【问题讨论】:

    标签: javascript fabricjs


    【解决方案1】:

    我认为使用loadFromJSONenlivenObjects 来实现这一点不是很好。 如果您在运行撤消/重做时加载了大量的 svg,则需要一些时间来渲染,重新加载所有内容以进行小的更改(如对象的位置)也没有多大意义。 我的想法是使用两个堆栈,您将在其中使用结构事件保存对象的修改。 你可以看看这里:

    fabric.StaticCanvas.prototype.getObjectByName  = function(name){
      if(!name || typeof name === 'undefined'){
      return [];
      }
      return this._objects.filter(function(o) {
          return o.name === name;
        });
    }
    var canvas = new fabric.Canvas('fabriccanvas');
    
    canvas.counter = 0;
    var newleft = 0;
    canvas.selection = false;
    var undoStack = [];
    var redoStack = [];
    addrect = function addrect(top, left, width, height, fill) {
        var rect = new fabric.Rect({
            top: document.getElementById("fabriccanvas").height,
            name: 'rectangle ' + canvas.counter,
            left: 0 + newleft,
            width: 100,
            height: 100,
            fill: '#' + (0x1000000 + (Math.random()) * 0xffffff).toString(16).substr(1, 6),
            //fix attributes applied for all rects
            opacity: 0.75,
            lockRotation: true,
            originX: 'left',
            originY: 'bottom',
            cornerSize: 15,
            hasRotatingPoint: false,
            perPixelTargetFind: true,
            minScaleLimit: 1
        })
        canvas.add(rect);
        undoStack.push({
         type:'added',
         object : rect
        })
        canvas.counter++;
        newleft += 100;
        redoStack=[];
    }
    var state = [];
    var mods = 0;
    var props = {};
    canvas.on(
        'mouse:down', function (e) {
        var block = e.target;
        if(block){
        	 props.oldStage = {
           left:block.left,
           top:block.top,
           width:block.width,
           height:block.height,
           scaleX:block.scaleX,
           scaleY:block.scaleY,
           }
        }
    }).on(
        'mouse:up', function (e) {
        var block = e.target;
        if(block){
        	 props.newStage = {
           left:block.left,
           top:block.top,
           width:block.width,
           height:block.height,
           scaleX:block.scaleX,
           scaleY:block.scaleY,
           }
           undoStack.push({
            objectName : block.name,
            type:'modified',
            oldStage:props.oldStage,
            newStage:props.newStage
           });
           props={};
        }
    });
    
    
    
    undo = function undo() {
        if(undoStack.length){
         var undoData = undoStack.pop();
         if(undoData && undoData.type){
           switch(undoData.type){
             case 'added':
             var objectByName = canvas.getObjectByName(undoData.object.name);
             if(objectByName.length){
               canvas.remove(objectByName[0]);
              
             }
             break;
             case 'modified':
             var objectByName = canvas.getObjectByName(undoData.objectName);
             if(objectByName.length){
              	for(var key in undoData.oldStage){
                  objectByName[0].set(key, undoData.oldStage[key]);
                }
             }
             break;
           }
           canvas.renderAll();
         }
         redoStack.push(undoData);
        }
    }
    
    redo = function redo() {
        if(redoStack.length){
         var redoData = redoStack.pop();
         if(redoData && redoData.type){
           switch(redoData.type){
             case 'added':
             if(redoData.object){
               canvas.add(redoData.object);
              
             }
             break;
             case 'modified':
             var objectByName = canvas.getObjectByName(redoData.objectName);
             if(objectByName.length){
              	for(var key in redoData.newStage){
                  objectByName[0].set(key, redoData.newStage[key]);
                }
             }
             break;
           }
           canvas.renderAll();
         }
         undoStack.push(redoData);
        }
    }
    clearcan = function clearcan() {
        canvas.clear().renderAll();
        canvas.counter=0;
        undoStack=[];
        redoStack=[];
        newleft = 0;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.6/fabric.js"></script>
    <input type="button" value="addrect" onclick="addrect()">
    <input type="button" value="undo" onclick="undo()">
    <input type="button" value="redo" onclick="redo()">
    <input type="button" value="clear" onclick="clearcan()">
    <br/>
    <canvas id="fabriccanvas" width="600" height="200" style="border:1px solid #ccc"></canvas>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-06
      • 2021-06-30
      • 2020-04-20
      • 2017-03-19
      • 2017-12-26
      • 2015-08-10
      • 2011-03-18
      相关资源
      最近更新 更多