如何通过FabricJS中的边界框对齐对象?

时间:2017-12-11 21:45:32

标签: fabricjs

想知道是否有办法通过边界框对齐FabricJs中的对象?

我正在使用obj.getBoundingRect()函数来确定对象bounders,然后将它们与Active的一个边界框(BB)坐标(我移动的那个)进行比较。如果我看到某些东西落在某个间隙之间(比如10px),我通过使用.setTop()属性将活动对象top命名为与可比元素相同的顶部。

问题是TOP不是正确的属性,因为边界框的顶部可能在元素之间不同。例如,具有相同顶部但角度不同的2个元素将具有不同的边界框顶部...

希望你看到我的观点...

https://jsfiddle.net/redlive/hwcu1p4f/

var canvas = this.__canvas = new fabric.Canvas('canvas');
//fabric.Object.prototype.transparentCorners = false;

var red = new fabric.Rect({
	id: 1,
  left: 100,
  top: 50,
  width: 100,
  height: 100,
  fill: 'red',
  angle: 0,
  padding: 10
});
canvas.add(red);

var green = new fabric.Rect({
	id: 2,
  left: 250,
  top: 180,
  width: 100,
  height: 100,
  fill: 'green',
  angle: 45,
  padding: 10
});
canvas.add(green);
canvas.renderAll();

canvas.on("object:moving", function(e){
	const draggableObj = e.target;
  const draggableObjBound = draggableObj.getBoundingRect();
  
  canvas.forEachObject(function(obj) {
    if (obj.id !== draggableObj.id) {
      var bound = obj.getBoundingRect();
      if (draggableObjBound.top > bound.top - 10 && draggableObjBound.top < bound.top + 10) {
        draggableObj.setTop(obj.getTop());
      }
    }
  });
});

canvas.forEachObject(function(obj) {
  var setCoords = obj.setCoords.bind(obj);
  obj.on({
    moving: setCoords,
    scaling: setCoords,
    rotating: setCoords
  });
});

canvas.on('after:render', function() {
  canvas.contextContainer.strokeStyle = '#555';
  canvas.forEachObject(function(obj) {
    var bound = obj.getBoundingRect();
    canvas.contextContainer.strokeRect(
      bound.left,
      bound.top,
      bound.width,
      bound.height
    );
  })
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.0.0-rc.3/fabric.js"></script>
<canvas id="canvas" width="800" height="500" style="border:1px solid #ccc"></canvas>

1 个答案:

答案 0 :(得分:2)

你应该使用中心来对齐它们,这不会改变。

对齐左边5的边界框,例如:

1)计算边界框。 2)考虑到中心,将对象的位置设置为5 + bb.width / 2.

在这种情况下,边界线对齐。

var canvas = this.__canvas = new fabric.Canvas('canvas');
//fabric.Object.prototype.transparentCorners = false;

var red = new fabric.Rect({
	id: 1,
  left: 100,
  top: 50,
  width: 100,
  height: 100,
  fill: 'red',
  angle: 0,
  padding: 10
});
canvas.add(red);

var green = new fabric.Rect({
	id: 2,
  left: 250,
  top: 180,
  width: 100,
  height: 100,
  fill: 'green',
  angle: 45,
  padding: 10
});
canvas.add(green);

//ALIGN EVERYTHING TO 5
canvas.forEachObject(function(object) {
  var bb = object.getBoundingRect();
  object.setPositionByOrigin({ x: 5 + bb.width/2, y: bb.top }, 'center', 'center');
  object.setCoords();
});


canvas.renderAll();


canvas.on("object:moving", function(e){
	const draggableObj = e.target;
  const draggableObjBound = draggableObj.getBoundingRect(true, true);
  
  canvas.forEachObject(function(obj) {
    if (obj.id !== draggableObj.id) {
      var bound = obj.getBoundingRect(true, true);
      if (draggableObjBound.top > bound.top - 10 && draggableObjBound.top < bound.top + 10) {
        draggableObj.setPositionByOrigin({ x: draggableObj.left, y: bound.top + draggableObjBound.height/2 }, draggableObj.originX, 'center');
      }
    }
  });
});

canvas.forEachObject(function(obj) {
  var setCoords = obj.setCoords.bind(obj);
  obj.on({
    moving: setCoords,
    scaling: setCoords,
    rotating: setCoords
  });
});

canvas.on('after:render', function() {
  canvas.contextContainer.strokeStyle = '#555';
  canvas.forEachObject(function(obj) {
    var bound = obj.getBoundingRect(true, true);
    canvas.contextContainer.strokeRect(
      bound.left,
      bound.top,
      bound.width,
      bound.height
    );
  })
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.0.0-rc.3/fabric.js"></script>
<canvas id="canvas" width="800" height="500" style="border:1px solid #ccc"></canvas>