我正在尝试使用 JSON.stringify 保存fabricjs stickman示例并使用 canvas.loadFromJSON 将其加载回来,我甚至添加了circle line1的属性,line2,line3和line4 使用以下方式显式地向JSON
var jsonSave = JSON.stringify(canvas.toJSON(['line1', 'line2', 'line3', 'line4']));
虽然我可以看到保存的JSON包含上面提到的属性,但是当我从JSON加载并尝试移动圆圈时出现错误,因为未捕获的TypeError:p.line1.set不是函数< /强>
我不明白为什么在保存设置之前是一个函数但是从JSON保存和加载之后不是吗?
还有其他任何方法可以让stickman在不使用 set方法的情况下工作,这样在我们保存并从JSON加载后它就不会中断。
我确实查找了类似的问题,这个链接是我能找到的最类似的问题但是这个答案中提供的解决方案似乎也没有解决保存和加载的问题。
loading stickman from json does not persist line coordinate rotation logic
我还附上了下面的小提琴链接。重现场景
http://jsfiddle.net/hkundnani/h0sf3x5h/5/
任何帮助将不胜感激..谢谢..
答案 0 :(得分:2)
当您的代码创建圆形对象时,您的代码会向圆形对象添加额外的属性(例如line1,line2,line3,line4)。这些额外属性是对结构画布上现有线对象的引用。您遇到的问题是JSON格式没有内置支持通过引用序列化对象。对象始终按值序列化。因此,对同一对象的多个引用将序列化为JSON字符串,作为具有相同值的多个对象。反序列化JSON字符串时,您将拥有多个具有相同值的对象,而不是对同一对象的多个引用。为了进一步解决您的问题,FabricJS的loadFromJSON()方法将顶级对象转换为FabricJS对象,但将内部属性对象(例如circle.line1)保留为普通对象。这些普通对象不具有FabricJS方法(例如,没有set方法)。
如果你在谷歌搜索&#34; JSON对象引用&#34;然后你会找到讨论以JSON格式保存对象引用问题的可能工作的文章。
在您的情况下,可能的解决方案可能是将自定义属性(例如&#34; $ id&#34;)添加到行对象,其中自定义属性包含行对象的唯一标识符。将此自定义属性保存到JSON字符串。加载JSON字符串后,您可以扫描FabricJS画布以查找线对象,并创建从标识符到线对象的映射。然后,您可以扫描FabricJS画布以查找圆形对象,并将其线属性值替换为地图中的线对象引用。这不是一个简单的解决方案,但应该可行。
答案 1 :(得分:1)
fabricjs的可能解决方法: http://jsfiddle.net/h0sf3x5h/9/ (片段不运行,如果你知道如何解决它,请告诉我)
重点是在保存和加载功能中编写自定义代码,以便再次将线条附加到您的圈子中。
var canvas = this.__canvas = new fabric.Canvas('c', { selection: false }), saveNow, loadNow;
fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';
(function() {
saveNow = (function(){
var jsonSave = JSON.stringify(canvas.toJSON(['linesID', 'selection', 'id']));
sessionStorage.canvase = jsonSave;
});
function _callBack() {
var objs = canvas.getObjects();
var lines = {};
for(var i = 0; i < objs.length; i++) {
if (objs[i].type === 'line') {
lines[objs[i].id] = objs[i];
}
}
for(i = 0; i < objs.length; i++) {
if (objs[i].type === 'circle') {
var circle = objs[i];
if (circle.linesID) {
circle.line1 = lines[circle.linesID[0]];
circle.line2 = lines[circle.linesID[1]];
circle.line3 = lines[circle.linesID[2]];
circle.line4 = lines[circle.linesID[3]];
}
}
}
canvas.renderAll();
}
loadNow = (function(){
var jsonLoad = sessionStorage.canvase;
canvas.loadFromJSON(jsonLoad, _callBack);
});
document.getElementById('save').addEventListener('click', saveNow);
document.getElementById('load').addEventListener('click', loadNow);
function makeCircle(left, top, line1, line2, line3, line4) {
var c = new fabric.Circle({
left: left,
top: top,
strokeWidth: 5,
radius: 12,
fill: '#fff',
stroke: '#666'
});
c.hasControls = c.hasBorders = false;
c.line1 = line1;
c.line2 = line2;
c.line3 = line3;
c.line4 = line4;
c.linesID = [line1 && line1.id, line2 && line2.id, line3 && line3.id, line4 && line4.id];
return c;
}
function makeLine(coords, id) {
return new fabric.Line(coords, {
fill: 'red',
stroke: 'red',
strokeWidth: 5,
selectable: false,
id: id
});
}
var line = makeLine([ 250, 125, 250, 175 ], 'line1'),
line2 = makeLine([ 250, 175, 250, 250 ], 'line2'),
line3 = makeLine([ 250, 250, 300, 350], 'line3'),
line4 = makeLine([ 250, 250, 200, 350], 'line4'),
line5 = makeLine([ 250, 175, 175, 225 ], 'line5'),
line6 = makeLine([ 250, 175, 325, 225 ], 'line6');
canvas.add(line, line2, line3, line4, line5, line6);
canvas.add(
makeCircle(line.get('x1'), line.get('y1'), null, line),
makeCircle(line.get('x2'), line.get('y2'), line, line2, line5, line6),
makeCircle(line2.get('x2'), line2.get('y2'), line2, line3, line4),
makeCircle(line3.get('x2'), line3.get('y2'), line3),
makeCircle(line4.get('x2'), line4.get('y2'), line4),
makeCircle(line5.get('x2'), line5.get('y2'), line5),
makeCircle(line6.get('x2'), line6.get('y2'), line6)
);
canvas.on('object:moving', function(e) {
var p = e.target;
p.line1 && p.line1.set({ 'x2': p.left, 'y2': p.top });
p.line2 && p.line2.set({ 'x1': p.left, 'y1': p.top });
p.line3 && p.line3.set({ 'x1': p.left, 'y1': p.top });
p.line4 && p.line4.set({ 'x1': p.left, 'y1': p.top });
canvas.renderAll();
});
})();
&#13;
<script src="http://fabricjs.com/lib/fabric.js"></script>
<canvas id="c" width="500" height="500"></canvas>
<button id="save">Save </button>
<button id="load">Load </button>
&#13;