问题
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>
回答1:
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>
来源:https://stackoverflow.com/questions/49697408/fabricjs-preserve-events-on-saving-getting-canvas-from-json