无法在FabricJS中还原已保存的多重选择

时间:2018-08-02 00:18:03

标签: fabricjs fabricjs2

您能帮我弄清楚这里发生了什么吗?

基本上我想将FabricJS与ReactJS和Redux一起使用。我想将当前选定的对象存储在redux存储中。但是,在保存多重选择的活动对象时,似乎有一种奇怪的行为。

let selectedObjects = null;
let canvas = new fabric.Canvas('canvas-area', {
  preserveObjectStacking: true,
  width: 500,
  height: 500
});

canvas.add(new fabric.Rect({
  left: 100,
  top: 100,
  fill: 'blue',
  width: 100,
  height: 100
}));

canvas.add(new fabric.Circle({
  radius: 50,
  fill: 'green',
  left: 200,
  top: 200
}));

canvas.renderAll();

// =======================

document.querySelector('#save-selection').addEventListener('click', ()=> {
  //selectedObjects = Object.assign({}, canvas.getActiveObject());
  selectedObjects = canvas.getActiveObject();
  canvas.discardActiveObject();
  canvas.renderAll();
});

document.querySelector('#apply-saved-selection').addEventListener('click', ()=> {
	canvas.setActiveObject(selectedObjects);
  canvas.renderAll();
});
<html>
  <body>
    <button id='save-selection'>Save Selection</button>
    <button id='apply-saved-selection'>Apply Saved Selection</button>
    <canvas id='canvas-area'></canvas>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.3.3/fabric.min.js"></script>
  </body>
</html>

基本上,您使用上面代码段的方式是:

用例1:单个所选对象

  1. 选择一个对象。
  2. 点击保存选择(它将保存当前选择的对象并清除当前画布选择)。
  3. 点击应用保存的选择
  4. 拖动当前选定的对象,所选内容和选定的对象保持同步,并且应用程序按预期运行。

用例2:多项选择

  1. 选择多个对象。
  2. 点击保存选择
  3. 点击应用保存的选择
  4. 拖动当前选择的对象,如您所见,仅拖动选择,实际选择的对象被保留(不同步)。

您能帮我弄清楚如何正确保存所选对象以便以后使用吗?

预先感谢

注意: 我正在使用最新的FabricJS(2.3.3)

1 个答案:

答案 0 :(得分:0)

更新

将选定的元素存储在redux存储中是不明智的。特别是当我们处理分组选择,分组对象,剪切的图像等时,很难重新加载保存的选定元素。

底线,请勿将所选元素保存在redux存储中。

=================

更新

我下面的回答有一个缺陷,那就是当加载保存的旋转选择时,该选择的旋转角度不会保留。

仍在寻找比我目前更好的答案。

=================

好吧,看来我们在重新加载多个选定对象时需要采取不同的方法。

摘要

我们需要使用画布中与保存的选择内的对象相对应的确切对象来创建新选择。

// Extend fabric js so that all objects inside the canvas
// will have the custom id attribute
// We will use this later to determine which is which
fabric.Object.prototype.id = undefined;

let selectedObjects = null;
let canvas = new fabric.Canvas('canvas-area', {
  preserveObjectStacking: true,
  width: 500,
  height: 500
});

canvas.add(new fabric.Rect({
  id: 'unique-id-01',
  left: 100,
  top: 100,
  fill: 'blue',
  width: 100,
  height: 100
}));
canvas.add(new fabric.Circle({
  id: 'unique-id-02',
  radius: 50,
  fill: 'green',
  left: 200,
  top: 200
}));
canvas.add(new fabric.Rect({
  id: 'unique-id-03',
  left: 300,
  top: 300,
  fill: 'red',
  width: 100,
  height: 100
}));
canvas.renderAll();


// =======================

document.querySelector('#save-selection').addEventListener('click', ()=> {
  //selectedObjects = Object.assign({}, canvas.getActiveObject());
  selectedObjects = canvas.getActiveObject();
  canvas.discardActiveObject();
  canvas.renderAll();
});

document.querySelector('#apply-saved-selection').addEventListener('click', ()=> {

  if (selectedObjects.type === 'activeSelection') {
  	
    let canvasObjects = canvas.getObjects(); // Get all the objects in the canvas
    let selObjs = [];
    
    // Loop through all the selected objects
    // Then loop through all the objects in the canvas
    // Then check the id of each objects if they matched
    // Then store the matching objects to the array
    for (let so of selectedObjects._objects) {
    	for (let obj of canvasObjects) {
      	if (obj.id === so.id) {
        	selObjs.push(obj); // Store the canvasObjects item, not the selectedObjects item.
          break;
        }
      }
    }
    
    // Create a new selection instance using the filtered objects above
    let selection = new fabric.ActiveSelection(selObjs, {
    	canvas: canvas
    });
    
    canvas.setActiveObject(selection); // Profit
    
  } else { // Single object selected, load directly
  	canvas.setActiveObject(selectedObjects);
  }
  
  canvas.renderAll();
});
<html>
  <body>
    <button id='save-selection'>Save Selection</button>
    <button id='apply-saved-selection'>Apply Saved Selection</button>
    <canvas id='canvas-area'></canvas>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.3.3/fabric.min.js"></script>
  </body>
</html>

  1. 我们需要扩展fabric js并添加自定义 id 属性。 稍后我们将使用它在fabric js实例内部的对象和保存的选择内部的对象之间进行比较。

  2. 遍历Fabric js实例对象和已保存的选择对象,并使用我们之前添加的自定义 id 确定在Fabric JS实例中选择了哪些对象。

  3. 使用步骤2中过滤的对象创建新的选择实例, new fabric.ActiveSelection

  4. fabric.ActiveSelection 实例设置为fabric js实例的 activeObject

  5. 利润

Fabric JS Selection Handling Reference