Reputation: 13620
I am trying to synchronize the move,resize and rotate operations of two fabric objects.
Consider there are two polygons - Poly1 and Poly2. When Poly1 is modified in any manner, I need to apply the same modification on Poly2 and need to get the updated points for Poly2. Below is the approach being followed :
Get the transform matrices of Poly1 before and after modification.
Use them to get the matrix which modified the transform matrix from its original to the modified state.
Multiply the matrix from the above step to the current transform matrix of Poly2 to get the new transform matrix.
Use the new transform matrix and get the updated points and redraw Poly2.
However, this approach is only working for move operation. If you do resize or rotate on Poly1, the same is not being applied correctly on Poly2. Please let me know what I am doing wrong here.
Thanks in advance for any help!!
Sample code - Blue is Poly1 and Red is Poly2
var oldPoly1Matrix;
var canvas = new fabric.Canvas('c');
var srcOptions = {
stroke: 'blue',
fill: '',
type: 'src'
};
var destOptions = {
stroke: 'red',
fill: '',
selectable: false,
hasControls: false,
hasBorders: false,
type: 'dest'
};
var poly1 = new fabric.Polygon([{
x: 60,
y: 40
}, {
x: 160,
y: 40
}, {
x: 160,
y: 140
}, {
x: 60,
y: 140
}], srcOptions);
var poly2 = new fabric.Polygon([{
x: 60,
y: 300
}, {
x: 160,
y: 300
}, {
x: 160,
y: 400
}, {
x: 60,
y: 400
}], destOptions);
canvas.add(poly1).add(poly2);
oldPoly1Matrix = poly1.calcTransformMatrix();
var originalPoly2Matrix = poly2.calcTransformMatrix();
poly2.matrix = originalPoly2Matrix;
function updatePoly2() {
var newPoly1Matrix = poly1.calcTransformMatrix();
var oldPoly1MatrixInverted = fabric.util.invertTransform(oldPoly1Matrix);
//newMatrix = oldMatrix * someMatrix
//therefore,someMatrix = newMatrix / oldMatrix = newMatrix * inverse(oldMatrix);
var diffMatrix = fabric.util.multiplyTransformMatrices(newPoly1Matrix, oldPoly1MatrixInverted);
var oldPoly2Matrix = poly2.matrix;
//Apply the same someMatrix to find out the new transform matrix for poly2.
var newPoly2Matrix = fabric.util.multiplyTransformMatrices(oldPoly2Matrix, diffMatrix);
var updatedPoints = poly2.get('points')
.map(function(p) {
return new fabric.Point(p.x - poly2.minX - poly2.width / 2, p.y - poly2.minY - poly2.height / 2);
})
.map(function(p) {
return fabric.util.transformPoint(p, newPoly2Matrix);
});
oldPoly1Matrix = newPoly1Matrix;
poly2.remove();
poly2 = new fabric.Polygon(updatedPoints, destOptions);
poly2.matrix = newPoly2Matrix;
canvas.add(poly2);
}
canvas {
border: 1px solid;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.19/fabric.js"></script>
<canvas id="c" height="500" width="600"></canvas>
<button id="update" onclick="updatePoly2()">
Update red shape
</button>
jsfiddle - https://jsfiddle.net/btxp0ck6/
Upvotes: 2
Views: 1777
Reputation: 13620
It is working fine after changing the translateX and translateY calculation from matrix mulplication to simple subtraction.Posting the code here for reference.
var oldPoly1Matrix;
var canvas = new fabric.Canvas('c');
var srcOptions = {
stroke: 'blue',
fill: '',
type: 'src'
};
var destOptions = {
stroke: 'red',
fill: '',
selectable: false,
hasControls: false,
hasBorders: false,
type: 'dest'
};
var poly1 = new fabric.Polygon([{
x: 60,
y: 40
}, {
x: 160,
y: 40
}, {
x: 160,
y: 140
}, {
x: 60,
y: 140
}], srcOptions);
var poly2 = new fabric.Polygon([{
x: 60,
y: 300
}, {
x: 160,
y: 300
}, {
x: 160,
y: 400
}, {
x: 60,
y: 400
}], destOptions);
canvas.add(poly1).add(poly2);
oldPoly1Matrix = poly1.calcTransformMatrix();
var originalPoly2Matrix = poly2.calcTransformMatrix();
poly2.matrix = originalPoly2Matrix;
function updatePoly2() {
var newPoly1Matrix = poly1.calcTransformMatrix();
var oldPoly1MatrixInverted = fabric.util.invertTransform(oldPoly1Matrix);
//newMatrix = oldMatrix * someMatrix
//therefore,someMatrix = newMatrix / oldMatrix = newMatrix * inverse(oldMatrix);
var diffMatrix = fabric.util.multiplyTransformMatrices(newPoly1Matrix, oldPoly1MatrixInverted,true);
diffMatrix[4] = newPoly1Matrix[4] - oldPoly1Matrix[4];
diffMatrix[5] = newPoly1Matrix[5] - oldPoly1Matrix[5];
var oldPoly2Matrix = poly2.calcTransformMatrix();
//Apply the same someMatrix to find out the new transform matrix for poly2.
var newPoly2Matrix = fabric.util.multiplyTransformMatrices(oldPoly2Matrix, diffMatrix,true);
newPoly2Matrix[4] = oldPoly2Matrix[4] + diffMatrix[4];
newPoly2Matrix[5] = oldPoly2Matrix[5] + diffMatrix[5];
var updatedPoints = poly2.get('points')
.map(function(p) {
return new fabric.Point(p.x - poly2.minX - poly2.width / 2, p.y - poly2.minY - poly2.height / 2);
})
.map(function(p) {
return fabric.util.transformPoint(p, newPoly2Matrix);
});
oldPoly1Matrix = newPoly1Matrix;
poly2.remove();
poly2 = new fabric.Polygon(updatedPoints, destOptions);
poly2.matrix = newPoly2Matrix;
canvas.add(poly2);
}
canvas {
border: 1px solid;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.7.19/fabric.js"></script>
<canvas id="c" height="500" width="600"></canvas>
<button id="update" onclick="updatePoly2()">
Update red shape
</button>
Jsfiddle - https://jsfiddle.net/btxp0ck6/1/
Upvotes: 3