Reputation: 479
I'm using fabricJS
with Angular
when I want to align an element to left for example I'm using the following method
alignLeft() {
// Get Selected Elements
var obj = this.canvas.getActiveObject();
// if no element is selected
if (obj !== undefined) {
// Bounding Box of the selected element
var bound = obj.getBoundingRect();
obj.set('left', (obj.left - bound.left));
//this.canvas.getActiveObject().setCoords();
this.canvas.renderAll();
}
}
The alignment works like a charm only then the zoom is in 100%, if I change the zoom or pan the canvas everything goes in the wrong way. Bellow is the methods I use for zooming In/Out
this.canvas.on('mouse:wheel', function (opt) {
var delta = opt.e.deltaY;
var zoom = this.canvas.getZoom();
zoom *= 0.999 ** delta;
if (zoom > 20) zoom = 20;
if (zoom < 0.01) zoom = 0.01;
this.canvas.zoomToPoint({ x: opt.e.offsetX, y: opt.e.offsetY }, zoom.toFixed(4));
opt.e.preventDefault();
opt.e.stopPropagation();
}.bind(this));
this.canvas.on('mouse:down', function (opt) {
var evt = opt.e;
if (evt.altKey === true) {
this.isDragging = true;
this.selection = false;
this.lastPosX = evt.clientX;
this.lastPosY = evt.clientY;
}
});
this.canvas.on('mouse:move', function (opt) {
if (this.isDragging) {
var e = opt.e;
var vpt = this.viewportTransform;
vpt[4] += e.clientX - this.lastPosX;
vpt[5] += e.clientY - this.lastPosY;
this.requestRenderAll();
this.lastPosX = e.clientX;
this.lastPosY = e.clientY;
}
});
this.canvas.on('mouse:up', function (opt) {
// on mouse up we want to recalculate new interaction
// for all objects, so we call setViewportTransform
this.setViewportTransform(this.viewportTransform);
this.isDragging = false;
this.selection = true;
});
After I read multiple questions and the fabricJS Documentation I changed the alignLeft()
method to the following:
alignLeft() {
// Get Selected Elements
var obj = this.canvas.getActiveObject();
// if no element is selected
if (obj !== undefined) {
// Bounding Box of the selected element
var bound = obj.getBoundingRect();
let p = {x: (obj.width / 2), y: obj.top}
var invertedMatrix = fabric.util.invertTransform(this.canvas.viewportTransform);
let newp = fabric.util.transformPoint(p, invertedMatrix);
obj.set('left', newp.x);
//this.canvas.getActiveObject().setCoords();
this.canvas.renderAll();
}
}
Upvotes: 4
Views: 1509
Reputation: 122
You need to user ViewPortCoordinates
(see fabricJS Docs) to get top left
, top right
, bottom left
, bottom right
coordinates of the canvas
according the the view port.
Describe canvas element extension over design properties are tl,tr,bl,br. if canvas is not zoomed/panned those points are the four corner of canvas if canvas is viewportTransformed you those points indicate the extension of canvas element in plain untrasformed coordinates The coordinates get updated with @method calcViewportBoundaries.
for alignLeft()
method you can update it to the following:
alignLeft() {
// Get Selected Elements
var obj = this.canvas.getActiveObject();
// if no element is selected
if (obj !== undefined) {
const viwePortCoords = this.canvas.vptCoords;
obj.set('left', viwePortCoords.bl.x + (obj.width / 2));
this.canvas.renderAll();
}
this.canvas.fire('object:modified', { target: obj });
}
Upvotes: 1