如何从多选的 activeObjects[] 元素中获取原始坐标?

How can I obtain the original coordinates from the activeObjects[] elements of a multiple selection?

我正在使用 Fabricjs 编写网页代码。首先,我在我的 canvas 中画了一些圆圈,然后我允许用户 select 其中一个或多个。我编写了一个 selection:created 处理程序,它创建一个表单并打印该表单中每个 selected 对象的坐标。 问题是这些坐标与我创建圆圈时设置的坐标完全不同。但是,只有当用户 select 两个或更多圈子时才会发生这种情况。

我基本上做的是:我调用 getActiveObjects() 方法 returns 一个 activeObjects[] 数组,然后我循环访问该数组的每个元素的 left 和 top 属性。我也尝试按照这个答案建议对这些数字进行相同的操作:

这是我创建圈子的方式:

function drawCircle( x, y, r, color ){
    var circle = new fabric.Circle({radius: r, fill: color, originX: 'center', originY: 'center', left: x, top: y, lockMovementX: true, lockMovementY: true, hasControls: false});
    canvas.add(circle);
}

这是 selection:created 处理程序:

canvas.on('selection:created', function(e){
    var activeObjects = canvas.getActiveObjects();
    var length = activeObjects.length;
    var myForm = document.createElement("form");

    for( var i=0; i<length; i++){                   
        var x = document.createElement("input");
        x.setAttribute('type',"text");
        x.setAttribute('name', "x"+i);
        x.setAttribute('value', activeObjects[i].left);

        var y = document.createElement("input");
        y.setAttribute('type',"text");
        y.setAttribute('name', "y"+i);
        y.setAttribute('value', activeObjects[i].top );

        var radius = document.createElement("input");
        radius.setAttribute('type',"text");
        radius.setAttribute('name', "radius"+i);
        radius.setAttribute('value', activeObjects[i].radius );

        f.appendChild(radius);
        f.appendChild(x);
        f.appendChild(y);                   
    }
})

我希望如果我创建两个调用 drawCircle(10,20,2,'black') 和 drawCircle(30,30,2,'black') 的圆并且我 select它们,我将以值 10、20、2、30、30 和 2 的形式读取;相反,只有半径值是正确的,但坐标分别是 (-10, 395) 和 (10, 405)。可以看到,两个圆圈之间的距离还是一样的,但是它们的坐标和原来的完全不一样。 此外,如果我修改 selection(假设我 select 3 个圆圈),我将在表格中读取其他完全不同的值。

var canvas = new fabric.Canvas('myCanvas');

fabric.Group.prototype.lockMovementX = true;
fabric.Group.prototype.lockMovementY = true;
fabric.Group.prototype.hasControls = false;

var circle = new fabric.Circle({radius: 2, fill: 'black', originX: 'center', originY: 'center', left: 10, top: 400-20, lockMovementX: true, lockMovementY: true, hasControls: false});
canvas.add(circle);

var circle = new fabric.Circle({radius: 2, fill: 'black', originX: 'center', originY: 'center', left: 30, top: 400-30, lockMovementX: true, lockMovementY: true, hasControls: false});
canvas.add(circle);

canvas.on('selection:created', function(e){
  var activeObjects = canvas.getActiveObjects();
  var length = activeObjects.length;
  
  var activeSelection = canvas.getActiveObject();
  var matrix = activeSelection.calcTransformMatrix();
  
  var form = document.createElement("form");
  
  for( var i=0; i<length; i++){
    var obj = activeObjects[i];
    var objectPosition = { x: obj.left, y: obj.top };
    var finalPosition = fabric.util.transformPoint(objectPosition, matrix);                       

      var radius = document.createElement("input");
      radius.setAttribute('type',"text");
      radius.setAttribute('name', "raggio"+i);
      radius.setAttribute('value', obj.radius );
      
      var x = document.createElement("input");
      x.setAttribute('type',"text");
      x.setAttribute('name', "x"+i);
      x.setAttribute('value', finalPosition.x );

      var y = document.createElement("input");
      y.setAttribute('type',"text");
      y.setAttribute('name', "y"+i);
      y.setAttribute('value', 400-finalPosition.y );

      form.appendChild(radius);
      form.appendChild(x);
      form.appendChild(y);
     }     

     document.getElementsByTagName('body')[0].appendChild(form);     
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.6/fabric.min.js"></script>


<h1> Grid </h1>

<canvas id="myCanvas" width="600" height="400" style="border: 1px solid #000000;"></canvas>

你必须考虑组应用的对象的变换。 当你刚刚选择时你可能认为没有转换,但 fabricjs 正在围绕选择的中心绘制那些圆圈,有一个平移操作。

解决任何变换(缩放、旋转)的一般方法是:

var canvas = new fabric.Canvas('myCanvas');

fabric.Group.prototype.lockMovementX = true;
fabric.Group.prototype.lockMovementY = true;
fabric.Group.prototype.hasControls = false;

var circle = new fabric.Circle({radius: 2, fill: 'black', originX: 'center', originY: 'center', left: 10, top: 20, lockMovementX: true, lockMovementY: true, hasControls: false});
canvas.add(circle);

var circle = new fabric.Circle({radius: 2, fill: 'black', originX: 'center', originY: 'center', left: 30, top: 30, lockMovementX: true, lockMovementY: true, hasControls: false});
canvas.add(circle);

canvas.on('selection:created', function(e){
  var activeObjects = canvas.getActiveObjects();
  var length = activeObjects.length;
  
  var activeSelection = canvas.getActiveObject();
  var matrix = activeSelection.calcTransformMatrix();
  
  var form = document.createElement("form");
  
  for( var i=0; i<length; i++){
    var obj = activeObjects[i];
    var objectPosition = { x: obj.left, y: obj.top };
    var finalPosition = fabric.util.transformPoint(objectPosition, matrix);                       

      var radius = document.createElement("input");
      radius.setAttribute('type',"text");
      radius.setAttribute('name', "raggio"+i);
      radius.setAttribute('value', obj.radius );
      
      var x = document.createElement("input");
      x.setAttribute('type',"text");
      x.setAttribute('name', "x"+i);
      x.setAttribute('value', finalPosition.x );

      var y = document.createElement("input");
      y.setAttribute('type',"text");
      y.setAttribute('name', "y"+i);
      y.setAttribute('value', finalPosition.y );

      form.appendChild(radius);
      form.appendChild(x);
      form.appendChild(y);
     }     

     document.getElementsByTagName('body')[0].appendChild(form);     
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.6/fabric.min.js"></script>


<h1> Grid </h1>

<canvas id="myCanvas" width="100" height="100" style="border: 1px solid #000000;"></canvas>

现在我用你的代码更新了我的答案,这对我来说很可靠。