Reputation: 73918
I have a DIV who has been transformed using a matrix.
I need to calculate some information for its bounding rectangles size.
Specifically I need found out: Width, Height, Rotation (deg from the matrix)
I cannot use Element.getBoundingClientRect()
I am manly interesting in a math solution, assuming that I have all the data needed to perform the rendering of div in advance (like: top, left position) any feedbacks is welcome.
In the example, the green box is a visual rappresentation of the dimension I need to found out.
#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>
Upvotes: 1
Views: 585
Reputation: 1241
When you say "without DOM operations" I assume that you have all the data needed to perform the calculation by hand in advance. Specifically, you have the (left, top)
coordinates and width/height
dimensions of the pre-transformed rectangle, and you also have the details of each transformation that was applied to the rectangle, and in the correct order. In this case, I would first build four points as follows, which represents the pre-transformed rectangle:
p1 = (left, top)
p2 = (left + width, top)
p3 = (left, top + height)
p4 = (left + width, top + height)
Then I would apply the transformation chain to each of these four points, to get p1'
, p2'
, p3'
, p4'
.
Then I would run over each p'
, and max/min the top/left
coordinates of all of them:
max_top
min_top
max_left
min_left
Now, from that information I can derive that:
(min_left, min_top)
will give us the top-left point of the bounding rect.(max_left - min_left, max_top - min_top)
will give us the dimensions of the bounding rect.However, It would be easier if you could just query for the element's transformation matrix, and break its components into floats. Then use a JS math library (such as numericJS) to build a transformation matrix out of these components, and use it to transform your points.
Here is a snippet that can be used to extract a numericJS matrix out of an element's CSS transform
property:
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]];
}
You can now use it to transform a given point:
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);
Upvotes: 1