seldary
seldary

Reputation: 6256

Bounding box offset of fabricjs path

I'm trying to create a shape by using a fabric.Path, and I would like to be able to rotate it around its center. Problem is, that the bounding box is offset, and the actual shape dances around its center:

enter image description here

this.canvas = new fabric.Canvas('c')
this.canvas.clear();

var triangle = new fabric.Triangle({
width: 20,
            height: 20,
            fill: '#35a2da',
left: 410,
top: 350,
angle: 90
});


var path = new fabric.Path(
  "M 200 175 A 25 25 0 1 0 217.678 217.678",
        {
        fill : '',
        stroke : '#35a2da',
        strokeWidth : 7,
        left: 200, 
        top:200
    });

var rotate = new fabric.Group([path, triangle], {left:200, top:200});

this.canvas.add(rotate);

The code above can be found here.

Upvotes: 2

Views: 3847

Answers (1)

natchiketa
natchiketa

Reputation: 5897

As long as you fix the dimensions of the fabric.Path object based on the SVG arc that you're drawing, and fix the dimensions of the fabric.Group to those same dimensions, you should be able to get the shape to be perfectly centered.

Example Fiddle

Reasons for explicity sizing

fabric.Path

The reason you want to explicitly set the width and height of the fabric.Path is because otherwise the default size will include the additional size from the stroke of the arc.

fabric.Group

The reason to explicitly set the size of the fabric.Group is because with the fabric.Triangle positioned at the start of the arc, the bounds will extend outside of that circle on which you want to be perfectly centered.

How to dynamically calculate the rotate icon SVG path

I wrote this function that returns an object with the points you'll need to render the SVG arc, given the radius:

function rotatePoints(radius) {
    // Get 45 degrees in radians
    var angle = Math.PI / 4;
    return {
        radius: radius,
        startPos: {
            x: radius,
            y: 0
        },
        endPos: {
            x: radius + (radius * Math.cos(angle)),
            y: radius + (radius * Math.sin(angle))
        }
    }
}

For example, given a radius of 30, you could build the SVG path like this:

var pathPts = rotatePoints(30);
var pathSVG = [
    'M', pathPts.startPos.x, pathPts.startPos.y,
    'A', pathPts.radius, pathPts.radius,
    0, 1, 0,
    pathPts.endPos.x, pathPts.endPos.y
];    
pathSVG.join(' ') // result: "M 30 0 A 30 30 0 1 0 51.21320343559643 51.21320343559643"

Canvas Coordinates vs. Group Coordinates

Keep in mind that once you add the Path and Triangle to the Group, if you want to set the position of either, the coordinates are relative to the bounds of the Group, not the whole canvas (see the fiddle for an example of how their positions are adjusted being added to the Group.

Upvotes: 0

Related Questions