29

Fabric.js の元に戻す/やり直しの組み込みサポートはありますか? [http://printio.ru/][1] でこのキャンセルとリピートをどのように使用したかを教えてください。

4

9 に答える 9

6

これに答えるのが遅いことはわかっていますが、これはこれを実装する私のバージョンです。誰かに役立つことができます。

Canvas States を として保存することで、この機能を実装しましたJSON。ユーザーが でオブジェクトを追加または変更するCanvasと、変更されたキャンバスの状態が保存され、array. これarrayは、ユーザーが [元に戻す] または [やり直し] ボタンをクリックするたびに操作されます。

このリンクを見てください。動作するデモ URL も提供しました。

https://github.com/abhi06991/Undo-Redo-Fabricjs

HTML:

<canvas id="canvas" width="400" height="400"></canvas> 
<button type="button" id="undo" >Undo</button>
<button type="button" id="redo" disabled>Redo</button>

JS:

var canvasDemo = (function(){
  var _canvasObject = new fabric.Canvas('canvas',{backgroundColor : "#f5deb3"});
    var _config = {
        canvasState             : [],
        currentStateIndex       : -1,
        undoStatus              : false,
        redoStatus              : false,
        undoFinishedStatus      : 1,
        redoFinishedStatus      : 1,
    undoButton              : document.getElementById('undo'),
        redoButton              : document.getElementById('redo'),
    };
    _canvasObject.on(
        'object:modified', function(){
            updateCanvasState();
        }
    );

  _canvasObject.on(
        'object:added', function(){
            updateCanvasState();
        }
    );

  var addObject = function(){
     var rect = new fabric.Rect({
            left   : 100,
            top    : 100,
            fill   : 'red',
            width  : 200,
            height : 200
    });
        _canvasObject.add(rect);
        _canvasObject.setActiveObject(rect);
    _canvasObject.renderAll();
  }

    var updateCanvasState = function() {
        if((_config.undoStatus == false && _config.redoStatus == false)){
            var jsonData        = _canvasObject.toJSON();
            var canvasAsJson        = JSON.stringify(jsonData);
            if(_config.currentStateIndex < _config.canvasState.length-1){
                var indexToBeInserted                  = _config.currentStateIndex+1;
                _config.canvasState[indexToBeInserted] = canvasAsJson;
                var numberOfElementsToRetain           = indexToBeInserted+1;
                _config.canvasState                    = _config.canvasState.splice(0,numberOfElementsToRetain);
            }else{
            _config.canvasState.push(canvasAsJson);
            }
        _config.currentStateIndex = _config.canvasState.length-1;
      if((_config.currentStateIndex == _config.canvasState.length-1) && _config.currentStateIndex != -1){
        _config.redoButton.disabled= "disabled";
      }
        }
    }


    var undo = function() {
        if(_config.undoFinishedStatus){
            if(_config.currentStateIndex == -1){
            _config.undoStatus = false;
            }
            else{
            if (_config.canvasState.length >= 1) {
            _config.undoFinishedStatus = 0;
              if(_config.currentStateIndex != 0){
                    _config.undoStatus = true;
                  _canvasObject.loadFromJSON(_config.canvasState[_config.currentStateIndex-1],function(){
                                var jsonData = JSON.parse(_config.canvasState[_config.currentStateIndex-1]);
                            _canvasObject.renderAll();
                        _config.undoStatus = false;
                        _config.currentStateIndex -= 1;
                                _config.undoButton.removeAttribute("disabled");
                                if(_config.currentStateIndex !== _config.canvasState.length-1){
                                    _config.redoButton.removeAttribute('disabled');
                                }
                            _config.undoFinishedStatus = 1;
                });
              }
              else if(_config.currentStateIndex == 0){
                _canvasObject.clear();
                        _config.undoFinishedStatus = 1;
                        _config.undoButton.disabled= "disabled";
                        _config.redoButton.removeAttribute('disabled');
                _config.currentStateIndex -= 1;
              }
            }
            }
        }
    }

    var redo = function() {
        if(_config.redoFinishedStatus){
            if((_config.currentStateIndex == _config.canvasState.length-1) && _config.currentStateIndex != -1){
                _config.redoButton.disabled= "disabled";
            }else{
            if (_config.canvasState.length > _config.currentStateIndex && _config.canvasState.length != 0){
                    _config.redoFinishedStatus = 0;
                _config.redoStatus = true;
              _canvasObject.loadFromJSON(_config.canvasState[_config.currentStateIndex+1],function(){
                            var jsonData = JSON.parse(_config.canvasState[_config.currentStateIndex+1]);
                        _canvasObject.renderAll();
                        _config.redoStatus = false;
                    _config.currentStateIndex += 1;
                            if(_config.currentStateIndex != -1){
                                _config.undoButton.removeAttribute('disabled');
                            }
                        _config.redoFinishedStatus = 1;
            if((_config.currentStateIndex == _config.canvasState.length-1) && _config.currentStateIndex != -1){
              _config.redoButton.disabled= "disabled";
            }
              });
            }
            }
        }
    }


    return {
        addObject  : addObject,
        undoButton : _config.undoButton,
        redoButton : _config.redoButton,
        undo       : undo,
        redo       : redo,
  }


  })();



  canvasDemo.undoButton.addEventListener('click',function(){
        canvasDemo.undo();
    });

    canvasDemo.redoButton.addEventListener('click',function(){
        canvasDemo.redo();
    });
  canvasDemo.addObject();
于 2017-06-05T10:36:20.703 に答える
2

私のユース ケースは青写真に似た単純な形状を描くことだったので、キャンバス全体の状態を保存するオーバーヘッドについて心配する必要はありませんでした。同じ状況にある場合、これは非常に簡単に達成できます。このコードは、キャンバスの周りに 'wrapper' div があり、元に戻す/やり直し機能を標準の Windows キーストローク 'CTRL+Z' と 'CTRL+Y' にバインドする必要があることを前提としています。

「pause_ Saving」変数の目的は、キャンバスが再レンダリングされたときに各オブジェクトが 1 つずつ作成されたように見えるという事実を説明することでした。本当に新しいイベント。

//variables for undo/redo
let pause_saving = false;
let undo_stack = []
let redo_stack = []

canvas.on('object:added', function(event){
    if (!pause_saving) {
        undo_stack.push(JSON.stringify(canvas));
        redo_stack = [];
        console.log('Object added, state saved', undo_stack);
    }

});
canvas.on('object:modified', function(event){
    if (!pause_saving) {
        undo_stack.push(JSON.stringify(canvas));
        redo_stack = [];
        console.log('Object modified, state saved', undo_stack);
    }
});
canvas.on('object:removed', function(event){
    if (!pause_saving) {
        undo_stack.push(JSON.stringify(canvas));
        redo_stack = [];
        console.log('Object removed, state saved', undo_stack);
    }
});

//Listen for undo/redo 
wrapper.addEventListener('keydown', function(event){
    //Undo - CTRL+Z
    if (event.ctrlKey && event.keyCode == 90) {
        pause_saving=true;
        redo_stack.push(undo_stack.pop());
        let previous_state = undo_stack[undo_stack.length-1];
        if (previous_state == null) {
            previous_state = '{}';
        }
        canvas.loadFromJSON(previous_state,function(){
            canvas.renderAll();
        })
        pause_saving=false;
    }
    //Redo - CTRL+Y
    else if (event.ctrlKey && event.keyCode == 89) {
        pause_saving=true;
        state = redo_stack.pop();
        if (state != null) {
            undo_stack.push(state);
            canvas.loadFromJSON(state,function(){
                canvas.renderAll();
            })
            pause_saving=false;
        }
    }
});
于 2019-07-10T20:06:01.570 に答える
0

そのために「object:added」および/または「object:removed」を使用できます — fabricjs.com/events

この投稿に従うことができます: Fabric.js にキャンバス Modified イベントがありますか?

于 2013-09-27T06:38:10.320 に答える
0

答えがすでに選択されていることは知っていますが、これが私のバージョンです。スクリプトは要約されており、元の状態へのリセットも追加されています。保存したいイベントの後、saveState(); を呼び出すだけです。jsフィドル

    canvas = new fabric.Canvas('canvas', {
        selection: false
    });
function saveState(currentAction) {
    currentAction = currentAction || '';
    // if (currentAction !== '' && lastAction !== currentAction) {
        $(".redo").val($(".undo").val());
        $(".undo").val(JSON.stringify(canvas));
        console.log("Saving After " + currentAction);
        lastAction = currentAction;
    // }
    var objects = canvas.getObjects();
    for (i in objects) {
        if (objects.hasOwnProperty(i)) {
            objects[i].setCoords();
        }
    }
}
canvas.on('object:modified', function (e) {
   saveState("modified");
});
// Undo Canvas Change
function undo() {
    canvas.loadFromJSON($(".redo").val(), canvas.renderAll.bind(canvas));
}
// Redo Canvas Change
function redo() {
    canvas.loadFromJSON($(".undo").val(), canvas.renderAll.bind(canvas));
};
$("#reset").click(function () {
    canvas.loadFromJSON($("#original_canvas").val(),canvas.renderAll.bind(canvas));
});

var bgnd = new fabric.Image.fromURL('https://s3-eu-west-1.amazonaws.com/kienzle.dev.cors/img/image2.png', function(oImg){
    oImg.hasBorders = false;
    oImg.hasControls = false;
    // ... Modify other attributes
    canvas.insertAt(oImg,0);
    canvas.setActiveObject(oImg);
    myImg = canvas.getActiveObject();
    saveState("render");
    $("#original_canvas").val(JSON.stringify(canvas.toJSON()));
});

$("#undoButton").click(function () {
    undo();
});
$("#redoButton").click(function () {
    redo();
});
于 2015-01-27T19:30:27.007 に答える
-2

私はあなたのすべての質問に答えています:)笑顔でこのリンクをチェックしてください..すべて完了しました...コピーして貼り付けてください:P http://jsfiddle.net/SpgGV/27/

var canvas = new fabric.Canvas('c');
var current;
var list = [];
var state = [];
var index = 0;
var index2 = 0;
var action = false;
var refresh = true;
state[0] = JSON.stringify(canvas.toDatalessJSON());
console.log(JSON.stringify(canvas.toDatalessJSON()));
$("#clear").click(function(){
canvas.clear();
index=0;
});
$("#addtext").click(function(){
++index;
action=true;  
var text = new fabric.Text('Sample', {
fontFamily: 'Hoefler Text',
left: 100,
top: 100,
//textAlign: 'center',
fill: 'navy',

});
canvas.add(text);   
}); 
canvas.on("object:added", function (e) {

if(action===true){

var object = e.target;
console.log(JSON.stringify(canvas.toDatalessJSON()));
state[index] = JSON.stringify(canvas.toDatalessJSON());
refresh = true;
action=false;
canvas.renderAll();
}
});
function undo() {

if (index < 0) {
index = 0;
canvas.loadFromJSON(state[index]);
canvas.renderAll();
return;
}


console.log('undo');

canvas.loadFromJSON(state[index]);

console.log(JSON.stringify(canvas.toDatalessJSON()));
canvas.renderAll();
action = false;
}

function redo() {

action = false;
if (index >= state.length - 1) {
canvas.loadFromJSON(state[index]);
canvas.renderAll();
return;
}

console.log('redo');

canvas.loadFromJSON(state[index]);

console.log(JSON.stringify(canvas.toDatalessJSON()));
canvas.renderAll();

canvas.renderAll();

}

canvas.on("object:modified", function (e) {
var object = e.target;
console.log('object:modified');
console.log(JSON.stringify(canvas.toDatalessJSON()));
state[++index] = JSON.stringify(canvas.toDatalessJSON());
action=false;
});

$('#undo').click(function () {
index--;
undo();
});
$('#redo').click(function () {
index++;
redo();
});
于 2013-10-05T14:36:00.320 に答える
-2

私はあなたのために小さなスクリプトを開発しました.それがあなたに役立つことを願っています.このデモフィドルを参照してください .やり直しは完璧ではありませんが、元に戻すボタンを最低2回クリックしてから作業をやり直す必要があります.やり直しコードで簡単な条件を指定することで、この問題を簡単に解決できます. . //Html

<canvas id="c" width="400" height="200" style=" border-radius:25px 25px 25px 25px"></canvas>
  <br>
   <br>
 <input type="button" id="addtext" value="Add Text"/>
<input type="button" id="undo" value="Undo"/>
<input type="button" id="redo" value="redo"/>
<input type="button" id="clear" value="Clear Canvas"/>   

//脚本

  var canvas = new fabric.Canvas('c');
    var text = new fabric.Text('Sample', {
   fontFamily: 'Hoefler Text',
    left: 50,
   top: 30,
    //textAlign: 'center',
    fill: 'navy',

});
canvas.add(text);
var vall=10;    
var l=0;
var flag=0;
var k=1;
var yourJSONString = new Array();
canvas.observe('object:selected', function(e) {
    //yourJSONString = JSON.stringify(canvas);
    if(k!=10)
{   
yourJSONString[k] = JSON.stringify(canvas);
k++;
}
j = k;
    var activeObject = canvas.getActiveObject();
    });
$("#undo").click(function(){
     if(k-1!=0)
     {
     canvas.clear();
     canvas.loadFromJSON(yourJSONString[k-1]);
     k--;
     l++;
     } 
  canvas.renderAll();   
 });

$("#redo").click(function(){
    if(l > 1)
     {  
      canvas.clear();
      canvas.loadFromJSON(yourJSONString[k+1]);
       k++;
       l--;
      canvas.renderAll();   
     }
 });

$("#clear").click(function(){
    canvas.clear();
  });
 $("#addtext").click(function(){
var text = new fabric.Text('Sample', {
   fontFamily: 'Hoefler Text',
    left: 100,
    top: 100,
    //textAlign: 'center',
    fill: 'navy',

});
canvas.add(text);
}); 
于 2013-09-27T12:38:30.753 に答える