简体   繁体   English

Fabric js中的对象对齐

[英]object alignment in fabric js

I am trying to implement object alignment (ie Right, Center, Left, Top, Bottom) in canvas.我正在尝试在画布中实现对象对齐(即右、中、左、上、下)。 Lets say user selected one object (ie Text or Image) then if user hit the Align right option then that selected object should align to right side.假设用户选择了一个对象(即文本或图像),那么如果用户点击右对齐选项,那么所选对象应该与右侧对齐。

I have tried below 2 methods but no success.我尝试了以下两种方法,但没有成功。

 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>

I have only implemented Align Right, as i am not sure how to do alignment for other Alignment (Top,Bottom, Left, 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.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>

You can set left/top according as your need, then setCoords() .您可以根据需要设置左/上,然后setCoords() Check snippet.检查片段。

While the other answers put me on the right track, none of them really worked for rotated objects, the trick is to set the transform origin to center and work with getBoundingRect() like DivPusher pointed out.虽然其他答案让我走上了正确的轨道,但它们都没有真正适用于旋转的对象,诀窍是将变换原点设置为中心,并像 DivPusher 指出的那样使用 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('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>

Here is my implementation of setAlign method using FabricJS 2.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()
}

Durga's answer is not perfect, because if you rotate a box clockwise and click on the align left button, the box will be aligned by its top left corner, not by its actual left edge. Durga 的答案并不完美,因为如果您顺时针旋转一个框并单击左对齐按钮,则该框将按其左上角对齐,而不是按其实际左边缘对齐。

You need to use the getBoundingRect() function.您需要使用getBoundingRect()函数。 Demo:演示:

 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>

Below code helps me to achieve alignment within the group of objects in fabric js.. hope it will help you :下面的代码可以帮助我在fabric js中的对象组内实现对齐。希望对您有所帮助:

... ...

var activeObject = this.canvas.getActiveObject();
if (activeObject) {
  var groupWidth = activeObject.getBoundingRect().width;
  var groupHeight = activeObject.getBoundingRect().height;


  this.canvas.getActiveObjects().map((obj: any) => {
    var itemWidth = obj.getBoundingRect().width;
    var itemHeight = obj.getBoundingRect().height;
   
    switch (alignType) {
      case 'left':
        obj.set({
          left: -(groupWidth / 2),
          originX: 'left'
        });
        obj.setCoords();
        this.canvas.renderAll();
        break;
      case 'center':
        obj.set({
          left: (0 - itemWidth / 2),
          originX: 'left'
        });
        obj.setCoords();
        this.canvas.renderAll();

        break;
      case 'right':
        obj.set({
          left: (groupWidth / 2 - itemWidth / 2),
          originX: 'center'
        });
        obj.setCoords();
        this.canvas.renderAll();
        break;
        case 'top':
          if(groupHeight != itemHeight){
            obj.set({
              top:-groupHeight/2
              
            });
            obj.setCoords();
            this.canvas.renderAll();
          }
          break;
          case 'bottom':
          if(groupHeight != itemHeight){
            obj.set({
              
              top: groupHeight / 2 - itemHeight 
              
            
            });
            obj.setCoords();
            this.canvas.renderAll();
          }
          break;
      default:
        break;
    }
  });
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM