簡體   English   中英

撤消和重做畫布不按預期工作

[英]Undo and Redo Canvas Not Working as Expected

我有一個帶有可添加對象的畫布,以及撤消和重做按鈕。 正如你在我的例子中所看到的,我能夠撤消/重做一次,但事情就會破裂; 通過這個我的意思是我可以添加一個對象並刪除它,但是如果我移動添加的對象並點擊撤消,它應該移動到我以前的位置,但它會從畫布中消失。

我正在使用fabric.js 1.7.22。

我的代碼:

 var canvas = this.__canvas = new fabric.Canvas('canvas', { backgroundColor: 'grey', centeredScaling: true }); canvas.setWidth(400); canvas.setHeight(600); canvas. preserveObjectStacking = true; // Add Text function Addtext() { var text = new fabric.IText("Tape and Type...", { fontSize: 30, top: 10, left: 10, textAlign: "center", }); canvas.add(text); canvas.centerObject(text); canvas.setActiveObject(text); text.enterEditing(); text.selectAll(); canvas.renderAll(); canvas.isDrawingMode = false; } // Undo Redo canvas.on('object:added',function(){ if(!isRedoing){ h = []; } isRedoing = false; }); var isRedoing = false; var h = []; function undo(){ if(canvas._objects.length>0){ h.push(canvas._objects.pop()); canvas.renderAll(); } } function redo(){ if(h.length>0){ isRedoing = true; canvas.add(h.pop()); } } 
 <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"> <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.22/fabric.min.js"></script> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <a href="#" class="btn btn-dark" onclick="Addtext()">Add Text</a> <button onclick="undo()" type="button" class="btn btn-sm btn-dark"> <i class="material-icons">undo</i> </button> <button onclick="redo()" type="button" class="btn btn-sm btn-dark"> <i class="material-icons">redo</i> </button> <canvas id="canvas"></canvas> 

您需要添加某種狀態管理函數來處理畫布的狀態,並且每次發生更改時都能夠恢復和更新狀態。

可以通過添加或更新畫布( object:addedobject:modified畫布上的object:modified處理程序來處理)或通過undoredo操作來觸發更改。

為了避免這些undoredo操作與歷史記錄沖突並添加重復項,您需要在它們發生時標記它們,這就是canvas.loadFromJSON回調在畫布更新后實際觸發操作的方便之處。

我添加了它的一個功能示例,並添加了一些調試消息,以便代碼更容易理解。 在你習慣它之前,大部分都是有點密集的閱讀)

 const canvas = new fabric.Canvas('canvas', { backgroundColor: 'grey', centeredScaling: true }); canvas.setWidth(400); canvas.setHeight(600); canvas.preserveObjectStacking = true; var Addtext = () => { const text = new fabric.IText('Tape and Type...', { fontSize: 30, top: 10, left: 10, textAlign: 'center', }); canvas.add(text); canvas.centerObject(text); canvas.setActiveObject(text); text.enterEditing(); text.selectAll(); canvas.renderAll(); canvas.isDrawingMode = false; }; var canvasHistory = { state: [], currentStateIndex: -1, undoStatus: false, redoStatus: false, undoFinishedStatus: true, redoFinishedStatus: true, }; const updateHistory = () => { if (canvasHistory.undoStatus === true || canvasHistory.redoStatus === true) { console.log('Do not do anything, this got triggered automatically while the undo and redo actions were performed'); } else { const jsonData = canvas.toJSON(); const canvasAsJson = JSON.stringify(jsonData); // NOTE: This is to replace the canvasHistory when it gets rewritten 20180912:Alevale if (canvasHistory.currentStateIndex < canvasHistory.state.length - 1) { const indexToBeInserted = canvasHistory.currentStateIndex + 1; canvasHistory.state[indexToBeInserted] = canvasAsJson; const elementsToKeep = indexToBeInserted + 1; console.log(`History rewritten, preserved ${elementsToKeep} items`); canvasHistory.state = canvasHistory.state.splice(0, elementsToKeep); // NOTE: This happens when there is a new item pushed to the canvasHistory (normal case) 20180912:Alevale } else { console.log('push to canvasHistory'); canvasHistory.state.push(canvasAsJson); } canvasHistory.currentStateIndex = canvasHistory.state.length - 1; } }; canvas.on('object:added', () => { updateHistory(); }); canvas.on('object:modified', () => { updateHistory(); }); var undo = () => { if (canvasHistory.currentStateIndex - 1 === -1) { console.log('do not do anything anymore, you are going far to the past, before creation, there was nothing'); return; } if (canvasHistory.undoFinishedStatus) { canvasHistory.undoFinishedStatus = false; canvasHistory.undoStatus = true; canvas.loadFromJSON(canvasHistory.state[canvasHistory.currentStateIndex - 1], () => { canvas.renderAll(); canvasHistory.undoStatus = false; canvasHistory.currentStateIndex--; canvasHistory.undoFinishedStatus = true; }); } }; var redo = () => { if (canvasHistory.currentStateIndex + 1 === canvasHistory.state.length) { console.log('do not do anything anymore, you do not know what is after the present, do not mess with the future'); return; } if (canvasHistory.redoFinishedStatus) { canvasHistory.redoFinishedStatus = false; canvasHistory.redoStatus = true; canvas.loadFromJSON(canvasHistory.state[canvasHistory.currentStateIndex + 1], () => { canvas.renderAll(); canvasHistory.redoStatus = false; canvasHistory.currentStateIndex++; canvasHistory.redoFinishedStatus = true; }); } }; 
 <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"> <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.22/fabric.min.js"></script> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <a href="#" class="btn btn-dark" onclick="Addtext()">Add Text</a> <button onclick="undo()" type="button" class="btn btn-sm btn-dark"> <i class="material-icons">undo</i> </button> <button onclick="redo()" type="button" class="btn btn-sm btn-dark"> <i class="material-icons">redo</i> </button> <canvas id="canvas"></canvas> 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM