user13771321
user13771321

Reputation:

How to create object stick on center of parent object in FabricJS?

I have an object e.g circle and I want to add more circles on border of the parent circle that must be center aligned.

On the attached gif image you can see my cursor - it only allows me to create a child circle on border of the parent.

enter image description here

Till now I was only able to create the parent circle.

var circle = new fabric.Circle({
        strokeWidth: 1,
        stroke: "#222",
        noScaleCache: false,
        strokeUniform: true,
        scaleX: 1,
        scaleY: 1,
        left: canvas.getWidth() / 2,
        top: canvas.getHeight() / 2,
        radius: fabric.util.parseUnit(circleSize + 'in')
    });

Upvotes: 0

Views: 522

Answers (1)

A.RAZIK
A.RAZIK

Reputation: 434

Basically you need to calculate Euclidean distance between the circle that you want to draw and the main circle, and if the distance is near to the border of the main circle you just draw a circle at the mouse position where you clicked.

The distance is calculated using Math.hypot function.

And here is the code.

var canvas = new fabric.Canvas('c', {
  selection: false
});

var circleRadius = 100;

var c = new fabric.Circle({
  strokeWidth: 3,
  stroke: "#222",
  fill: "#55ff55",
  noScaleCache: false,
  strokeUniform: true,
  selectable: false,
  scaleX: 1,
  scaleY: 1,
  left: canvas.getWidth() / 2 - circleRadius,
  top: canvas.getHeight() / 2 - circleRadius,
  radius: circleRadius
});

canvas.add(c);

var circleAngle = Math.atan2(c.getCenterPoint().x,c.getCenterPoint().y);
var circle = new fabric.Circle({
  strokeWidth: 3,
  stroke: "#222",
  radius: 30,
  selectable: true,
  originX: 'center',
  originY: 'center',
  fill: "#ff5555ff",
  left: Math.sin(circleAngle) * circleRadius + canvas.getWidth() / 2,
  top: Math.cos(circleAngle) * circleRadius + canvas.getHeight() / 2
});

canvas.add(circle);

var isDown, origX, origY;

canvas.on('mouse:down', function(o) {
  var pointer = canvas.getPointer(o.e);
  origX = pointer.x;
  origY = pointer.y;
  if (isDown) {
    circle.set({
      strokeWidth: 3,
      stroke: "#222",
      radius: 30,
      left: pointer.x,
      top: pointer.y,
      fill: "#ff5555ff"
    });
    canvas.add(circle);
    circle = new fabric.Circle({
      strokeWidth: 3,
      stroke: "#222",
      radius: 1,
      selectable: true,
      originX: 'center',
      originY: 'center'
    });
    canvas.add(circle);
  }
});

canvas.on('mouse:move', function(o) {
  var pointer = canvas.getPointer(o.e);
  var x = pointer.x - c.getCenterPoint().x;
  var y = pointer.y - c.getCenterPoint().y;
  circle.set({
    strokeWidth: 3,
    stroke: "#222",
    radius: 30,
    left: Math.sin(Math.atan2(x,y))*c.radius + canvas.getWidth() / 2,
    top: Math.cos(Math.atan2(x,y))*c.radius + canvas.getHeight() / 2,
    fill: "#ff5555ff"
  });

  if (nearToBorder(pointer, c.getCenterPoint(), c.radius)) {
    isDown = true;
  } else {
    isDown = false;
  }
  canvas.renderAll();
});

canvas.on('mouse:up', function(o) {
  isDown = false;
});

function nearToBorder(pointer, circlePoint, r) {
  var d = Math.hypot(pointer.x - (circlePoint.x), pointer.y - (circlePoint.y));
  return d >= r - 10 && d <= r + 10;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.0.0-rc.1/fabric.min.js"></script>
<canvas id="c" width="500" height="500" style="border:1px solid #ccc"></canvas>

Upvotes: 1

Related Questions