7

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!

Virto111
  • 577
  • 4
  • 20

1 Answers1

2

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>
Durga
  • 15,263
  • 2
  • 28
  • 52
  • Thank you Durga, i also thought if that is possible (to override a rectangle shape) but i have never tried it. That might be a solution and i will try it. Regards! – Virto111 Sep 13 '18 at 12:35
  • @Virto111 have added creation from mouse event from [here](https://stackoverflow.com/a/17409472/3551786) – Durga Sep 13 '18 at 18:06