Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FabricJS - Preserve events on saving / getting canvas from JSON

Is there a way to "preserve" events when saving canvas to JSON and then get them bonded back on loadFromJSON

In the link below I've created an element redBox and bonded an event "moving" on it. After "restoring" canvas from JSON that event no longer available and it makes sense why...

The problem is, based on requirements, I have no idea what element could be in the JSON and what event was previously applied to it. Basically, I need dynamically apply all possible events on that particular element.

http://jsfiddle.net/redlive/rwdt6rwj/

fabric.util.object.extend(fabric.Image.prototype, {
		toObject: function() {
        return fabric.util.object.extend(this.callSuper('toObject'), {
            	sanboxValues: this.get('sanboxValues'),
          		imgSrc: this.get('imgSrc')
            }
            // name: this.get('name'),
        );
    },
    ddpLoadImage: function(imgSrc, sanboxValues){
    	this.setSrc(imgSrc, function(img){
        const {scaleFactor} = sanboxValues;
        img.scale( 1 / scaleFactor ).setCoords();
        img.set({
          clipTo:	function(ctx){
            const {x, y, width, height, scaleFactor} = this.sanboxValues;
            ctx.rect(
                x * scaleFactor - width / 2, 
                y * scaleFactor - height / 2, 
                width * scaleFactor, 
                height * scaleFactor
            );
          }
        });
        image.canvas.renderAll()
	  	}, {
		    sanboxValues,
    		imgSrc
			});
		}
});


let store;
const canvas = new fabric.Canvas('paper');
const canvasOriginalSize = {
	width: 600,
  height: 600
};

const image = new fabric.Image('', {
    left: 50,
    top: 50,
});

const redBox = new fabric.Rect({
    left: 0,
    top: 0,
    width: 50,
    height: 50,
    fill: 'red'
});


const page = new fabric.Rect({
    left: 50,
    top: 50,
    width: 300,
    height: 300
});

canvas.add(page);
canvas.add(image);
canvas.add(redBox);
canvas.renderAll();



canvas.on("object:modified", function(obj){
	console.log(obj.target);
});

redBox.on("moving", function(obj){
	console.log('Moving redBox');
});




const scaleFactor = 1;
const imgSrc = ['https://picsum.photos/', page.width * scaleFactor,'/',  page.height * scaleFactor].join('');
const x = 10, y = 7, width = page.width, height = page.height; 

image.ddpLoadImage(imgSrc, {x, y, width, height, scaleFactor});

  
  
  
  
  
$("#save").on('click', function(){
	store = canvas.toJSON();
  console.log(store);
});
    
$("#restore").on('click', function(){
	canvas.loadFromJSON(store, function(){
      canvas.getObjects().forEach((obj)=>{
          if (obj.type === 'image') {
						obj.ddpLoadImage(obj.imgSrc, obj.sanboxValues);
          }
      });
    	canvas.renderAll();
	});
});
    
#paper {
  border: solid 1px red;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/fabric.js/2.2.3/fabric.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img id="image" />
<canvas id="paper" width="400" height="400" style="border:1px solid #ccc"></canvas>
<button id="save">Save to JSON</button>
<button id="restore">Restore form JSON</button>
like image 546
Eugene Vilder Avatar asked Oct 17 '25 13:10

Eugene Vilder


1 Answers

You have to again attach events to objects. In loadFromJSON 3rd arguments which is reviver having object from json and fabric object. Add event to fabric objects.

DEMO

fabric.util.object.extend(fabric.Image.prototype, {
  toObject: function() {
    return fabric.util.object.extend(this.callSuper('toObject'), {
        sanboxValues: this.get('sanboxValues'),
        imgSrc: this.get('imgSrc')
      }
      // name: this.get('name'),
    );
  },
  ddpLoadImage: function(imgSrc, sanboxValues) {
    this.setSrc(imgSrc, function(img) {
      const {
        scaleFactor
      } = sanboxValues;
      img.scale(1 / scaleFactor).setCoords();
      img.set({
        clipTo: function(ctx) {
          const {
            x,
            y,
            width,
            height,
            scaleFactor
          } = this.sanboxValues;
          ctx.rect(
            x * scaleFactor - width / 2,
            y * scaleFactor - height / 2,
            width * scaleFactor,
            height * scaleFactor
          );
        }
      });
      image.canvas.renderAll()
    }, {
      sanboxValues,
      imgSrc
    });
  }
});


let store;
const canvas = new fabric.Canvas('paper');
const canvasOriginalSize = {
  width: 600,
  height: 600
};

const image = new fabric.Image('', {
  left: 50,
  top: 50,
});

const redBox = new fabric.Rect({
  left: 0,
  top: 0,
  width: 50,
  height: 50,
  fill: 'red',
  rectType: 'eventedRect'
});


const page = new fabric.Rect({
  left: 50,
  top: 50,
  width: 300,
  height: 300
});

canvas.add(page,image,redBox);

canvas.on("object:modified", function(obj) {
  console.log(obj.target);
});

redBox.on("moving", rectMoving);

function rectMoving(obj) {
  console.log('Moving redBox');
};

const scaleFactor = 1;
const imgSrc = ['https://picsum.photos/', page.width * scaleFactor, '/', page.height * scaleFactor].join('');
const x = 10,
  y = 7,
  width = page.width,
  height = page.height;

image.ddpLoadImage(imgSrc, {
  x,
  y,
  width,
  height,
  scaleFactor
});


$("#save").on('click', function() {
  store = canvas.toJSON(['rectType']);
  console.log(store);
});

$("#restore").on('click', function() {
  canvas.loadFromJSON(store, function() {
    canvas.renderAll();
  },function(o,object){
    if (object.rectType == 'eventedRect') {
      object.on("moving", rectMoving);
    }
    if (object.type === 'image') {
      object.ddpLoadImage(object.imgSrc, object.sanboxValues);
    }
  });
});
#paper {
  border: solid 1px red;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/fabric.js/2.2.3/fabric.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<img id="image" />
<canvas id="paper" width="400" height="400" style="border:1px solid #ccc"></canvas>
<button id="save">Save to JSON</button>
<button id="restore">Restore form JSON</button>
like image 129
Durga Avatar answered Oct 20 '25 03:10

Durga



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!