本文采用的版本为 fabric@6.0.0-rc2
-
Matrix 是一个 3 * 2 的矩阵,表示目标的缩放和平移。
[0]: 水平方向的缩放因子 (a)。
[1]: 水平方向的倾斜变换 (c),也可以被理解为在Y轴方向上倾斜对象。
[2]: 垂直方向的倾斜变换 (b),也可以被理解为在X轴方向上倾斜对象。
[3]: 垂直方向的缩放因子 (d)。
[4]: 水平方向的平移量 (e)。
[5]: 垂直方向的平移量 (f)。
-
Canvas.viewportTransform
表示画布的缩放和平移(即视口的变换)。
// 1. 在 800 * 600 的画布上创建一个矩形
var rect = new fabric.Rect({
width: 600,
height: 600,
left: 0,
top: 0,
fill: 'black',
strokeWidth: 0,
});
// 2. 修改 viewportTransform, 使得画布的中心点放到矩形的中心
const center = rect.getCenterPoint(); // {x: 300, y: 300}
const { viewportTransform, width, height } = canvas;
viewportTransform[4] = width / 2 - center.x * viewportTransform[0];
viewportTransform[5] = height / 2 - center.y * viewportTransform[3];
canvas.setViewportTransform(viewportTransform); // [1, 0, 0, 100, 0], 即水平方向移动了100px
console.log(viewportTransform);
发生 viewportTransform 变换后,相对于视口位置和相对于画布位置就不相等了。
// 3. 打印鼠标位置
canvas.on('mouse:down', (opt) => {
const event = opt.e;
console.log('scenePoint', canvas.getScenePoint(event));
console.log('viewPoint', canvas.getViewportPoint(event));
});
// 此时点击左上角
// scenePoint {x: -100, 0}
// viewPoint {x: 0, 0}
即 getScenePoint 获得的是当前相对于视口的位置,getViewportPoint 获得的是当前相对于画布的位置。
// 4. 在鼠标位置创建一个红色的方块,此时需采用相对于视口的位置
canvas.on('mouse:down', (opt) => {
const event = opt.e;
console.log('scenePoint', canvas.getScenePoint(event));
console.log('viewPoint', canvas.getViewportPoint(event));
const scenePoint = canvas.getScenePoint(event);
const redRect = new fabric.Rect({
width: 40,
height: 40,
fill: 'red',
strokeWidth: 0,
left: scenePoint.x - 40 / 2,
top: scenePoint.y - 40 / 2,
});
canvas.add(redRect);
canvas.renderAll();
});
-
Object matrix
- calcTransformMatrix: 返回当前对象相对于画布的矩阵变换,如果对象在一个Group中,这个方法返回的结果包括 Group 的矩阵变换。
- calcOwnMatrix: 返回当前对象的矩阵变换,不考虑其他的信息。
// 5. 创建一个Group 和 Rect
const rect2 = new fabric.Rect({
left: 0,
top: 0,
width: 100,
height: 50,
fill: 'green',
strokeWidth: 0,
});
const group = new fabric.Group([rect2], {
left: 100,
top: 100,
width: 100,
height: 100,
strokeWidth: 0,
});
canvas.add(group);
console.log('Group calcTransformMatrix', group.calcTransformMatrix());
console.log('calcTransformMatrix', rect2.calcTransformMatrix());
console.log('calcOwnMatrix', rect2.calcOwnMatrix());
// Group calcTransformMatrix [1, 0, 0, 1, 150, 125]
-
invertTransform
fabric.util.invertTransform 用于计算给定变换矩阵的逆矩阵。
假定在画布上存在两个矩形,希望一个矩形 Rect1 移动时,另一个矩形 Rect2 跟着进行移动(相对位置不变)。
Rect1 * Matrix = Rect2
Matrix 就是这个相对位置的变换矩阵
Rect1-Invert * Rect1 * Matrix = Rect1-Invert * Rect2
Rect1-Invert * Rect1 相消:
Matrix = Rect1-Invert * Rect2
相对位置的变换矩阵 = Rect1-Invert * Rect2
已知相对位置,无论 Rect1 怎么平移,都可以根据相对位置的变换矩阵得到 Rect2 的位置。
const rect1 = new fabric.Rect({
left: 0,
top: 0,
width: 100,
height: 50,
fill: 'red',
});
const rect2 = new fabric.Rect({
left: 100,
top: 300,
width: 100,
height: 50,
fill: 'green',
});
// 相对位置的变化矩阵
const desiredTransform = fabric.util.multiplyTransformMatrices(
fabric.util.invertTransform(rect1.calcTransformMatrix()),
rect2.calcTransformMatrix(),
);
rect1.on('moving', () => {
// 根据 rect1 的新地址和相对变换矩阵,计算得到 rect2 的新地址
const matrix = rect1.calcTransformMatrix();
const newMatrix = fabric.util.multiplyTransformMatrices(matrix, desiredTransform);
// 进行变换
fabric.util.applyTransformToObject(rect2, newMatrix);
canvas.renderAll();
});