javascript - Allineamento degli oggetti in fabricJS dopo zoom e pan
Sto usando fabricJS con Angular quando voglio allineare un elemento a sinistra, ad esempio sto usando il seguente metodo
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();
}
}
L'allineamento funziona alla perfezione solo quando lo zoom è al 100%, se cambio lo zoom o sposto la tela tutto va storto. Sotto ci sono i metodi che uso per lo zoom 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;
});
Dopo aver letto più domande e la documentazione di fabricJS, ho modificato il metodo alignLeft() come segue:
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();
}
}
Risposta n. 1
Devi usare ViewPortCoordinates (vedi documentazione di fabricJS) per ottenere le coordinate angolo in alto a sinistra, angolo in alto a destra, angolo in basso a sinistra, angolo in basso a destra del canvas secondo la vista della finestra.
Descrivere l'estensione dell'elemento canvas rispetto alle proprietà di design che sono tl, tr, bl, br. Se il canvas non è stato ingrandito/spostato, quei punti sono i quattro angoli del canvas; se il canvas è stato trasformato dalla viewport, quei punti indicano l'estensione dell'elemento canvas nelle coordinate semplici non trasformate. Le coordinate vengono aggiornate con @method calcViewportBoundaries.
per il metodo alignLeft() puoi aggiornarlo come segue:
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 });
}
