【问题标题】:object alignment in fabric jsFabric js中的对象对齐
【发布时间】:2018-05-04 15:56:09
【问题描述】:

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

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

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>

我只实现了右对齐,因为我不确定如何为其他对齐(上、下、左、中)进行对齐。

【问题讨论】:

  • 如果对象旋转了,你想如何对齐该对象?
  • 在与之前相同的位置。

标签: javascript jquery html5-canvas fabricjs


【解决方案1】:

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() || 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) {
  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;
  }
}
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>

您可以根据需要设置left/top,然后setCoords()。检查sn-p。

【讨论】:

  • 再次很棒。非常感谢。
  • 出于好奇,有没有更简单的方法可以在 fabric js 文档中找到一些东西。有时我无法找到我应该使用哪个功能以及我正在使用的功能是否已弃用等?
  • @DS9 你可以查看documentation sectionchange log
【解决方案2】:

虽然其他答案让我走上了正轨,但它们都没有真正适用于旋转对象,诀窍是将变换原点设置为中心并使用 getBoundingRect() 就像 DivPusher 指出的那样。

//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('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 an 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】:

这是我使用 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()
}

【讨论】:

    【解决方案4】:

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

    您需要使用 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>

    【讨论】:

      猜你喜欢
      • 2017-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-30
      • 2017-04-06
      • 1970-01-01
      • 1970-01-01
      • 2020-03-27
      相关资源
      最近更新 更多