我需要在 css transform: matrix()
之前计算元素的结束边界矩形应用了变换。我真的不知道从哪里开始,也找不到任何好的文章来解决这个问题。
所以假设你有元素的原始位置 getBoundingClientRect()
如果您有应该应用的矩阵,是否有可靠的方法来找到结束位置。
我已经构建了一个滚动 Controller ,我正在尝试通过屏幕映射元素进度,但我需要元素的开始和结束位置。所以我需要在应用 css 转换后元素的位置来确定元素何时离开屏幕。现在我只是应用矩阵然后运行getBoundingClientRect()
再次。但这似乎有点骇人听闻。
所以假设你有原始和结束矩阵。然后运行 getBoundingClientRect()
在元素上找到它的位置。有没有一种数学方法来计算新的边界矩形?
所以对于这个例子,我们将只使用一个 6 值矩阵。但也可以将其应用于完整的 16 值矩阵:
const boundingRect = element.getBoundingClientRect();
const startingMatrix = [1, 0, 0, 1, 0, 0];
const endingMatrix = [2, 1, -1, 2, 200, 400];
// Now calculate the new bounding rect of element after ending matrix is applied.
我根据这篇文章尝试了以下 https://dev.opera.com/articles/understanding-the-css-transforms-matrix/由下面的评论推荐。有一些我显然遗漏或不理解的东西。这是我的尝试:const applyToPoint = (matrix, point) => {
const multiplied = [
matrix[0] * point[0],
matrix[1] * point[1],
matrix[2] * point[0],
matrix[3] * point[1],
matrix[4] * point[0],
matrix[5] * point[1]
]
const result = [
multiplied[0] + multiplied[2] + multiplied[4],
multiplied[1] + multiplied[3] + multiplied[5]
]
return result
}
const box = document.querySelector('.box')
const startingMatrix = [1, 0, 0, 1, 0, 0]
box.style.transform = `matrix(1,0,0,1,0,0)`
const startingRect = box.getBoundingClientRect()
const endingMatrix = [2, 1, -1, 2, 200, 400]
box.style.transform = `matrix(2,1,-1,2,200,400)`
const endingRect = box.getBoundingClientRect()
const newPoint = applyToPoint(endingMatrix, [startingRect.x, startingRect.y])
console.log(newPoint, endingRect)
.box {
height: 50px;
width: 50px;
background: green;
margin: 50px 0;
}
<div class="box"></div>
我也试过:
const applyToPoint = (matrix, point) => [
matrix[0] * point[0] + matrix[2] * point[1] + matrix[4],
matrix[1] * point[0] + matrix[3] * point[1] + matrix[5]
]
任何帮助,将不胜感激。或指向正确方向的指针。
最佳答案
问题是您正在混合两个不同的坐标系:
getBoundingClientRect()
使用)transform
使用)如 linked article 中所述,
本地系统的原点是元素的中心:
When a transform is applied to an object, it creates a local coordinate system. By default, the origin — the (0,0) point — of the local coordinate system lies at the object's center
让我们调用
[xc, yc]
元素的中心。要转换一个点(在客户端系统中表示),您需要执行以下操作:
xc
和 yc
)xc
和 yc
)这是一个转换 4 个框 Angular 并计算相关边界框的代码:
var matrix = [2, 1, -1, 2, 200, 400];
var box = document.querySelector('.box');
var startingRect = box.getBoundingClientRect();
var xc = startingRect.left + startingRect.width/2;
var yc = startingRect.top + startingRect.height/2;
const applyMatrix = (matrix, point) => [
matrix[0] * point[0] + matrix[2] * point[1] + matrix[4],
matrix[1] * point[0] + matrix[3] * point[1] + matrix[5]
];
const clientToLocal = (point) => [point[0] - xc, point[1] - yc];
const localToClient = (point) => [point[0] + xc, point[1] + yc];
const transformPoint = (point) => localToClient(applyMatrix(matrix, clientToLocal(point)));
function getBoundingBox(pt1, pt2, pt3, pt4)
{
var x1 = Math.min(pt1[0], pt2[0], pt3[0], pt4[0]);
var y1 = Math.min(pt1[1], pt2[1], pt3[1], pt4[1]);
var x2 = Math.max(pt1[0], pt2[0], pt3[0], pt4[0]);
var y2 = Math.max(pt1[1], pt2[1], pt3[1], pt4[1]);
return {x: x1, y: y1, width: x2 - x1, height: y2 - y1};
}
var topLeft = [startingRect.left, startingRect.top];
var topRight = [startingRect.right, startingRect.top];
var bottomLeft = [startingRect.left, startingRect.bottom];
var bottomRight = [startingRect.right, startingRect.bottom];
var transformedBox = getBoundingBox(transformPoint(topLeft), transformPoint(topRight), transformPoint(bottomLeft), transformPoint(bottomRight));
console.log(transformedBox);
box.style.transform = 'matrix('+matrix.join()+')';
var endingRect = box.getBoundingClientRect();
console.log(endingRect);
输出:{x: 158, y: 400, width: 150, height: 150}
DOMRect {x: 158, y: 400, width: 150, height: 150, top: 400, …}
关于javascript - 有没有办法在应用 css 变换矩阵之前计算元素的结束位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71050881/