如何计算应用 CSS 转换矩阵的 DOM 元素的边界矩形大小?不使用 Element.getBoundingClient

How to calculate bounding rectangles size for a DOM element on which CSS transform matrix is applied? Without using Element.getBoundingClientRect()

本文关键字:边界 getBoundingClient Element 元素 DOM 应用 计算 CSS 转换 何计算      更新时间:2023-09-26

我有一个使用矩阵转换的DIV。

我需要计算其边界矩形大小的一些信息。

具体来说,我需要找出:宽度、高度、旋转(从矩阵度)

我不能使用Element.getBoundingClientRect()

我对数学解决方案非常感兴趣,假设我拥有提前执行div 渲染所需的所有数据(例如:顶部、左侧位置),欢迎任何反馈。

在示例中,绿色框是我需要找出的维度的视觉呈现。

#box {
  position: absolute;
  top: 100px;
  left: 100px;
  width: 200px;
  height: 200px;
  background-color: red;
  transform: matrix(0.707107, 0.707107, -0.707107, 0.707107, -0.707107, 34.6482);
}
#result {
  position: absolute;
  height: 282.8427734375px;
  left: 57.871490478515625px;
  top: 93.22679901123047px;
  width: 282.8428039550781px;
  border: 1px solid green;
}
<div id="box"></div>
<div id="result"></div>

当你说"没有DOM操作"时,我假设你已经拥有提前手动执行计算所需的所有数据。具体而言,您具有预转换矩形的(left, top)坐标和width/height尺寸,并且还具有应用于矩形的每个转换的详细信息,并且顺序正确。在这种情况下,我将首先构建四个点,如下所示,它们表示预转换的矩形:

  • p1 = (left, top)
  • p2 = (left + width, top)
  • p3 = (left, top + height)
  • p4 = (left + width, top + height)

然后,我将变换链应用于这四个点中的每一个,以获得p1'p2'p3'p4'

然后我会遍历每个p',并最大/最小值所有top/left坐标:

  • max_top
  • min_top
  • max_left
  • min_left

现在,从这些信息中我可以得出:

  • (min_left, min_top) 将给我们边界矩形的左上角。
  • (max_left - min_left, max_top - min_top) 将给我们边界矩形的尺寸。

但是,如果可以查询元素的转换矩阵并将其组件分解为浮点数,则会更容易。然后使用 JS 数学库(如 numericJS)从这些组件中构建一个转换矩阵,并使用它来转换你的点。

下面是一个代码片段,可用于从元素的 CSS transform 属性中提取 numericJS 矩阵:

getTransformationMatrix: function (element) {
    var transform = element.css('transform');
    // Verify that the returned result is valid
    if (transform && transform !== "none" && transform !== "") {
        // The returned string from 'element.css('transform')' has the following template - 'matrix(a, c, b, d, tx, ty)'. We would like to extract the values of a, b, c and d,
        // in order to use them to construct a Matrix object which will represent the following matrix:
        //   a b tx
        // ( c d ty )
        //   0 0 1
        // For more information, please see https://developer.mozilla.org/en-US/docs/Web/CSS/transform
        var transformValues = transform.split('(')[1].split(')')[0].split(',');
        var a = parseFloat(transformValues[0]);
        var c = parseFloat(transformValues[1]);
        var b = parseFloat(transformValues[2]);
        var d = parseFloat(transformValues[3]);
        var tx = parseFloat(transformValues[4]);
        var ty = parseFloat(transformValues[5]);
        return [[a, b, tx], [c, d, ty], [0, 0, 1]];
    }
    // return the identity matrix if no transformation is set on the element.
    return new [[1, 0 ,0], [0, 1, 0], [0, 0, 1]];
}

您现在可以使用它来转换给定点:

function getTransformedPoint(matrix, point) {
   return numeric.dot(matrix, [p.left, p.top, 1]);
}
var matrix = getTransformationMatrix(element);
transformedP1 = getTransformedPoint(matrix, p1);
transformedP2 = getTransformedPoint(matrix, p2);
transformedP3 = getTransformedPoint(matrix, p3);
transformedP4 = getTransformedPoint(matrix, p4);