Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fabric.js - Creating polyline shape via mouse drag does not center the shape to its bounding box

Tags:

fabricjs

I am creating a triangle with (polyline) tool trying to make an rectangle triangle. Everything is fine but the created triangle is not inside of it's bounding box and that causes an issue afterwards. I have already achieve that to crate an polygon and the polygon is centered inside of it's bounding box but applying the same techniques doesn't seem to work for the case of polyline triangle.

Image showing the unwanted effect

This jsFiddle is showing that unwanted behavior.

Maybe i have to change the 'originX' and the 'originY' but i tried several different combinations and it didn't worked out:

const triangle = new fabric.Polyline(calcPoints(originX, originY, originX, originY), {
objectCaching: false,
left: originX,
top: originY,
originX: 'left',
originY: 'top',
fill: '#0000FF',
includeDefaultValues: false});

I also use newShape.setPositionByOrigin method on mouse up:

newShape.setPositionByOrigin(position, 'top', 'left'); 

For the polygon case i also applied pathOffset for the shape, but here it is causing event bigger offset.

Is there any way to fix the shape to placed in the bounding box?

Regards!

like image 530
Virto111 Avatar asked Sep 11 '18 12:09

Virto111


1 Answers

If you need a rightangle triangle you can override fabric.Rect.

DEMO

var canvas = new fabric.Canvas("my-canvas", {
  backgroundColor: '#fff',
  width: 400,
  height: 400
});
fabric.RectangleTriangle = fabric.util.createClass(fabric.Rect, {
  type: 'rectangleTriangle',
  _render: function(ctx) {
    var w = this.width,
      h = this.height,
      x = -this.width / 2,
      y = -this.height / 2;
    ctx.beginPath();
    ctx.moveTo(x, y);
    ctx.lineTo(x, y + h);
    ctx.lineTo(x + w, y + h);
    ctx.lineTo(x, y);
    ctx.closePath();
    this._renderPaintInOrder(ctx);
  }
});
fabric.RectangleTriangle.fromObject = function(object, callback) {
  return fabric.Object._fromObject('RectangleTriangle', object, callback);
};
var rect, isDown, origX, origY;

function onMouseDown(o) {
  isDown = true;
  var pointer = canvas.getPointer(o.e);
  origX = pointer.x;
  origY = pointer.y;
  var pointer = canvas.getPointer(o.e);
  rect = new fabric.RectangleTriangle({
    left: origX,
    top: origY,
    width: pointer.x - origX,
    height: pointer.y - origY,
    fill: 'blue',
    selectable:false
  });
  canvas.add(rect);
};

function onMouseMove(o) {
  if (!isDown) return;
  var pointer = canvas.getPointer(o.e);

  if (origX > pointer.x) {
    rect.set({
      left: Math.abs(pointer.x)
    });
  }
  if (origY > pointer.y) {
    rect.set({
      top: Math.abs(pointer.y)
    });
  }

  rect.set({
    width: Math.abs(origX - pointer.x)
  });
  rect.set({
    height: Math.abs(origY - pointer.y)
  });
  canvas.renderAll();
};

function onMouseUp(o) {
  isDown = false;
  rect.setCoords();
};

function select() {
  canvas.off('mouse:up', onMouseUp);
  canvas.off('mouse:move', onMouseMove);
  canvas.off('mouse:down', onMouseDown);
  canvas.selection = true;
  objectSelectable(true);
}

function draw() {
  canvas.on('mouse:up', onMouseUp);
  canvas.on('mouse:move', onMouseMove);
  canvas.on('mouse:down', onMouseDown);
  canvas.selection = false;
  objectSelectable(false);
}

function objectSelectable(value) {
  canvas.forEachObject(function(obj) {
    obj.selectable = value;
  })
}
draw();
canvas{
  border:2px solid;
}
<script src="https://rawgithub.com/kangax/fabric.js/master/dist/fabric.js"></script>
<button onclick="select()">select</button>
<button onclick="draw()">draw</button>
<div id="wrapper">
	<canvas id="my-canvas"></canvas>
</div>
like image 187
Durga Avatar answered Nov 07 '22 18:11

Durga