javascript - Using stateProperties and hasStateChanged to implement undo / redo in fabric.js -


edit: scope of question has shifted bit. please see updates below.

i've been working on undo/redo of sorts fabric.js (see fiddle). though rather naive, it's working part (for adding / removing / moving or resizing individual objects or adding / removing groups of objects), not moving or resizing groups of objects. in fiddle, note console output onobjectselected() function.

to see mean, draw objects on fiddle canvas, , move or resize them individually. undo / redo works expected. however, when groups selected , moved, can't see how retrieve updated positions of objects within group, means undo / redo can't restore correct values.

// onobjectselected function quoted here satisfy stackoverflow  // question requirements. see full jsfiddle context. (i in canvas.getobjects()) {         if (canvas.item(i).active === true ) {             console.log(canvas.item(i));             selectedobject.push({                 "itemnum"   : i,                 "svdobject" : fabric.util.object.clone(canvas.item(i))             });         }     } 

the reason seems object positions / scales not updated when moved or resized group. i've tried various things, including running setcoords() objects, has not helped. i'd appreciate if can spot i'm doing wrong, or has idea how work around this.

edit: clarify, normal undo / redo system using 2 arrays store properties objects on canvas user modifies them. when undo or redo clicked, properties applied object on canvas. problem i'm having when groups of objects selected , subsequently modified, don't know how capture properties, such positions of objects in group, because properties of objects within group not updated when objects modified group reason.

update: i've learned when objects in user selected groups, object position recorded relative group it's in, , no longer canvas, makes sense. when dealing object in group, add it's left/top coord group left/top coord calculate coord of object relative canvas. scalex/y should multiplied group scalex/y.

update: i've mananaged want (see new fiddle). i've since learned fabric's 'stateful' flag, stateproperties array , hasstatechanged method, simplify things. documentation these sparse , i've not been successful far in using them within solution. usage tips or example code using these appreciated. specifically, able control properties saved, since don't need save changeable properties.

onobjectselected looks @ present:

function onobjectselected() {    selectedobject = [];    (i in canvas.getobjects()) {      if (canvas.item(i).active === true) {        // shft-ctrl-j see item properties on click (chrome)       console.log(canvas.item(i));        // objects can flipped, not groups        var groupleft = 0;       var grouptop = 0;       var groupscalex = 1;       var groupscaley = 1;       var groupangle = 0;         // if it's group, add group coords       if (typeof canvas.item(i).group != "undefined") {         var groupleft = canvas.item(i).group.left;         var grouptop = canvas.item(i).group.top;         var groupscalex = canvas.item(i).group.scalex;         var groupscaley = canvas.item(i).group.scaley;         var groupangle = canvas.item(i).group.angle;       }        selectedobject.push({         "itemnum": i,         "left": canvas.item(i).left + groupleft,         "top": canvas.item(i).top + grouptop,         "scalex": canvas.item(i).scalex * groupscalex,         "scaley": canvas.item(i).scaley * groupscaley,         "angle": canvas.item(i).angle + groupangle,         "flipx": canvas.item(i).flipx,         "flipy": canvas.item(i).flipy       });     }    }  }; 

fabricjs not support auto-scaling or positioning default. way support implement own scaling/positioning mechanisms. tried many things these lines work best @ moment.

so basically, please add these functions in js:

function prepareratio(o){     saveratio(o);     o.on('modified', function(e){         saveratio(o);     }); }  function restoreratio(o){     o.set({         left: o._ratio._left * _cv.width,         top: o._ratio._top * _cv.height,         width: o._ratio._width * _cv.width,         height: o._ratio._height * _cv.height     });      o.setcoords(); }  function saveratio(obj){     obj._ratio = {          _left: obj.left / _cv.width,         _top: obj.top / _cv.height,         _width: obj.width / _cv.width,         _height: obj.height / _cv.height     }; } 

i used 2 custom variables here _cv simplified structure arranged store width , height of target canvas, and, _ratio each objects (constant) ratio value.

and use them wisely when create object or resize canvas:

fabric.image.fromurl('xxxx.png', function(img) {      img.set({         // todo: give object width , height, left , top     });      // save ratio once create object     prepareratio(img);      canvas.add(img);      // optional: add own codes });  function redraw() {      // todo: resize canvas want      _cv = {         width: canvas.getwidth(),         height: canvas.getheight()     };      canvas.foreachobject(function(obj) {         // restore ratio every time when resize canvas         restoreratio(obj);     }); }  window.addeventlistener('resize', redraw, false); 

this looks little bit long simple , clear solution in fact. i'm pretty sure work in side. hope helps.


Comments

Popular posts from this blog

javascript - Jquery show_hide, what to add in order to make the page scroll to the bottom of the hidden field once button is clicked -

python - Django-cities exits with "killed" -

python - How to get a widget position inside it's layout in Kivy? -