结构js中的对象对齐

时间:2017-11-21 08:49:36

标签: javascript jquery canvas fabricjs

我正在尝试在画布中实现对象对齐(即右,中,左,上,下)。假设用户选择了一个对象(即文本或图像),然后如果用户点击右对齐选项,则所选对象应该对齐到右侧。

我尝试了以下两种方法但没有成功。



var canvas = new fabric.Canvas('a');
canvas.add(new fabric.Rect({
  left: 50,
  top: 50,
  height: 50,
  width: 50,
  fill: 'red'
}));
canvas.add(new fabric.Rect({
  left: 130,
  top: 50,
  height: 50,
  width: 50,
  fill: 'green'
}));
canvas.add(new fabric.Rect({
  left: 90,
  top: 130,
  height: 50,
  width: 50,
  fill: 'blue'
}));

canvas.renderAll();

$('.alignment').click(function() {
  var cur_value = $(this).attr('data-action');
  if (cur_value != '') {
    process_align(cur_value);
  } else {
    alert('Please select a item');
    return false;
  }
});

/* Align the selected object */
function process_align(val) {
  switch (val) {
    case 'right':
      //Tried below one with
      //activeObj.setPositionByOrigin(new fabric.Point(activeObj.top, canvas.getWidth()), activeObj.originY,'center');

      //Tried below one but its not working
      var activeObj = canvas.getActiveObject();
      activeObj.set({
        originX: 'right',
        //originY: 'center'
      });
      activeObj.setCoords();
      canvas.renderAll();
      break;
  }
}

canvas {
  border: 2px solid black;
}

<script src="https://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
<script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.19/fabric.js"></script>
<button class="alignment" data-action="left">Align Left</button>
<button class="alignment" data-action="center">Align Center</button>
<button class="alignment" data-action="right">Align Right</button>
<button class="alignment" data-action="top">Align Top</button>
<button class="alignment" data-action="bottom">Align Bottom</button>
<canvas id="a" width="400" height="200"></canvas>
&#13;
&#13;
&#13;

我只实现了右对齐,因为我不确定如何对其他对齐(顶部,底部,左侧,中央)进行对齐。

4 个答案:

答案 0 :(得分:4)

&#13;
&#13;
var canvas = new fabric.Canvas('a');
canvas.add(new fabric.Rect({
  left: 50,
  top: 50,
  height: 50,
  width: 50,
  fill: 'red'
}));
canvas.add(new fabric.Rect({
  left: 130,
  top: 50,
  height: 50,
  width: 50,
  fill: 'green'
}));
canvas.add(new fabric.Rect({
  left: 90,
  top: 130,
  height: 50,
  width: 50,
  fill: 'blue'
}));

canvas.renderAll();

$('.alignment').click(function() {
  var cur_value = $(this).attr('data-action');
  var activeObj = canvas.getActiveObject();
  if (cur_value != '' && activeObj) {
    process_align(cur_value, activeObj);
    activeObj.setCoords();
    canvas.renderAll();
  } else {
    alert('Please select a item');
    return false;
  }
});

/* Align the selected object */
function process_align(val, activeObj) {
  switch (val) {

    case 'left':
      activeObj.set({
        left: 0
      });
      break;
    case 'right':
      activeObj.set({
        left: canvas.width - (activeObj.width * activeObj.scaleX)
      });
      break;
    case 'top':
      activeObj.set({
        top: 0
      });
      break;
    case 'bottom':
      activeObj.set({
        top: canvas.height - (activeObj.height * activeObj.scaleY)
      });
      break;
    case 'center':
      activeObj.set({
        left: (canvas.width / 2) - ((activeObj.width * activeObj.scaleX) / 2)
      });
      break;
  }
}
&#13;
canvas {
  border: 2px solid black;
}
&#13;
<script
  src="https://code.jquery.com/jquery-2.2.4.min.js"
  integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
  crossorigin="anonymous"></script>
<script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.19/fabric.js"></script>
<button class="alignment" data-action="left">Align Left</button>
<button class="alignment" data-action="center">Align Center</button>
<button class="alignment" data-action="right">Align Right</button>
<button class="alignment" data-action="top">Align Top</button>
<button class="alignment" data-action="bottom">Align Bottom</button>
<canvas id="a" width="400" height="200"></canvas>
&#13;
&#13;
&#13;

您可以根据需要设置左/上,然后setCoords()。检查代码段。

答案 1 :(得分:1)

Durga的答案并不完美,因为如果顺时针旋转一个框并单击向左对齐按钮,则该框将按其左上角而不是其实际左边缘对齐。 / p>

您需要使用 getBoundingRect()函数。演示:

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

  var rect = new fabric.Rect({
    left: 100,
    top: 50,
    width: 100,
    height: 100,
    fill: 'green',
    angle: 20,
    padding: 0
  });
  canvas.add(rect);
  canvas.setActiveObject(canvas.item(0));

    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 = 'red';

    canvas.forEachObject(function(obj) {
      var bound = obj.getBoundingRect();

      canvas.contextContainer.strokeRect(
        bound.left + 0.5,
        bound.top + 0.5,
        bound.width,
        bound.height
      );
    })
  });


function alignLeft(){
	var obj = canvas.getActiveObject();
  var bound = obj.getBoundingRect();
  
  // console.log(bound.left);
  // console.log(obj.left);
  
  obj.set('left', (obj.left - bound.left));
  canvas.getActiveObject().setCoords();
  canvas.renderAll();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.3/fabric.min.js"></script>

<button onclick="alignLeft()">align real left</button>
<canvas id="c" width="500" height="300" style="border: 1px solid rgb(204, 204, 204); position: absolute; left: 0px; top: 0px; touch-action: none; user-select: none;" ></canvas>

答案 2 :(得分:1)

虽然其他答案使我走上了正确的轨道,但它们都不是真正适用于旋转对象的方法,但诀窍是将转换原点设置为居中并与DivBusher指出的getBoundingRect()一起使用。

//Override fabric transform origin to center
fabric.Object.prototype.set({
  originX:'center',
  originY:'center',
});


var canvas = new fabric.Canvas('a');
canvas.add(new fabric.Rect({
  left: 50,
  top: 50,
  height: 50,
  width: 50,
  fill: 'red'
}));
canvas.add(new fabric.Text('I love fabricjs', { 
    left: 200,
    top: 80, 
    fill: '#555',
    angle: 35,
    scaleX: .8,
    scaleY: .8,
}));
canvas.add(new fabric.Rect({
  left: 90,
  top: 130,
  height: 50,
  width: 50,
  fill: 'blue',
  angle: 45,
}));

canvas.renderAll();

$('.alignment').click(function() {
  var cur_value = $(this).attr('data-action');
  var activeObj = canvas.getActiveObject() || canvas.getActiveGroup();
  if (cur_value != '' && activeObj) {
    process_align(cur_value, activeObj);
    activeObj.setCoords();
    canvas.renderAll();
  } else {
    alert('Please select a item');
    return false;
  }
});

/* Align the selected object */
function process_align(val, activeObj) {
  
  const bound = activeObj.getBoundingRect()

  switch (val) {

    case 'left':
      activeObj.set({
        left: activeObj.left - bound.left 
      });
      break;
    case 'right':
      activeObj.set({
        left: canvas.width - bound.width/2
      });
      break;
    case 'top':
      activeObj.set({
        top: activeObj.top - bound.top
      });
      break;
    case 'bottom':
      activeObj.set({
        top: canvas.height - bound.height/2
      });
      break;
    case 'center':
      activeObj.set({
        left: canvas.width / 2
      });
      break;
    case 'middle':
      activeObj.set({
        top: canvas.height / 2
      });
      break;
  }
}
canvas {
  border: 2px solid black;
}
<script
  src="https://code.jquery.com/jquery-2.2.4.min.js"
  integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
  crossorigin="anonymous"></script>
<script type='text/javascript' src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.19/fabric.js"></script>
<button class="alignment" data-action="left">Align Left</button>
<button class="alignment" data-action="center">Align Center</button>
<button class="alignment" data-action="right">Align Right</button>
<button class="alignment" data-action="top">Align Top</button>
<button class="alignment" data-action="middle">Align Middle</button>
<button class="alignment" data-action="bottom">Align Bottom</button>
<canvas id="a" width="400" height="200"></canvas>

答案 3 :(得分:0)

这是我使用 FabricJS 2.0

实现的setAlign方法
setAlign(align, canvas) {
    let activeObj = canvas.getActiveObject(),
      horizontalCenter = (activeObj.width * activeObj.scaleX) / 2,
      verticalCenter = (activeObj.height * activeObj.scaleY) / 2,
      { width, height } = canvas

    switch (align) {
      case 'top':
        activeObj.set({ top: verticalCenter })
        break
      case 'left':
        activeObj.set({ left: horizontalCenter })
        break
      case 'bottom':
        activeObj.set({ top: height - verticalCenter })
        break
      case 'right':
        activeObj.set({ left: width - horizontalCenter })
        break
      case 'center':
        activeObj.set({ left: (width / 2) })
        break
      case 'middle':
        activeObj.set({ top: (height / 2) })
        break
    }

    activeObj.setCoords()
    canvas.renderAll()
}