如何在不考虑变换的情况下计算getBoundingClientRect()? [英] How to compute getBoundingClientRect() without considering transforms?
问题描述
getBoundingClientRect()
返回转换后屏幕上元素的坐标。如何在转换之前计算坐标?即没有变换。
getBoundingClientRect()
returns the coordinates of an element on the screen after being transformed. How do I calculate those coordinates before being transformed? i.e. without transforms.
我找到的最简单的方法是:
The simplest way I found was:
element.style.transform = 'none'; //temporarily reset the transform
var untransformedOffset = element.getBoundingClientRect().top; //get the value
element.style.transform = ''; //set it back
但这会导致布局抖动缓慢,尤其是在许多元素上完成时尤其明显。现场演示: http://jsbin.com/nibiqogosa/1/edit?js,控制台,输出
but that causes slow layout thrashing, especially noticeable if done on many elements. Live demo: http://jsbin.com/nibiqogosa/1/edit?js,console,output
有更好的方法吗?
该javascript代码可以应用于:
That javascript code can be applied to:
<div id="element"></div>
<style> #element { transform: translateY(20px); }</style>
结果将为0(不包括页面的保证金)
And the result will be 0 (excluding the page's margin)
元素.getBoundingClientRect()。top
的结果将是20(不包括页面边距)
The result of element.getBoundingClientRect().top
will be 20 (excluding the page's margin)
http://jsbin.com/kimaxojufe/1/edit?css,js,console,output
推荐答案
获取元素位置而不考虑元素和DOM树上的任何转换:
var el = element,
offsetLeft = 0,
offsetTop = 0;
do{
offsetLeft += el.offsetLeft;
offsetTop += el.offsetTop;
el = el.offsetParent;
} while( el );
获取元素位置而不考虑应用转换但是要保持对DOM树的任何转换。
为此,您可以尝试恢复转换。
您必须首先将 transform-origin
设置为 0,0,0
并围绕自己进行转换(缩放,旋转)宽度翻译(50%,50%)...翻译(-50%, - 50%)
。
这是一个例子,
更改:
To do so you could try to revert the transform.
You must first set transform-origin
to 0,0,0
and surround yourself your transformation (scale, rotate) width translate(50%,50%) ... translate(-50%, -50%)
.
Here is an example,
change that :
transform: scale(2) rotate(45deg) translate(20px);
transform-origin: 50% 50%; //default value
进入
transform: translate(50%, 50%) scale(2) rotate(45deg) translate(-50%,-50%) translate(20px);
transform-origin: 0 0 0;
我们需要这样做,因为getComputedStyle()返回的矩阵不包含使用转换完成的内容 - 起源。不知道为什么。
We need to do that because the matrix returned by getComputedStyle() does not include stuff done with transform-origin. Don't know really why.
然后你可以使用这段代码:
Then you can use this code :
function parseTransform(transform){
//add sanity check
return transform.split(/\(|,|\)/).slice(1,-1).map( function(v){
return parseFloat(v);
});
}
function convertCoord(transformArr, x, y, z){
//add sanity checks and default values
if( transformArr.length == 6 ){
//2D matrix
//need some math to apply inverse of matrix
var t = transformArr,
det = t[0]*t[3] - t[1]*t[2];
return {
x: ( x*t[3] - y*t[2] + t[2]*t[5] - t[4]*t[3] )/det,
y: ( -x*t[1] + y*t[0] + t[4]*t[1] - t[0]*t[5] )/det
}
}
else /*if (transformArr.length > 6)*/{
//3D matrix
//haven't done the calculation to apply inverse of 4x4 matrix
}
}
var elRect = element.getBoundingClientRect(),
st = window.getComputedStyle(element),
topLeft_pos = convertCoord(
parseTransform( st.transform ),
elRect.left,
elRect.top,
st.perspective
);
我不会解释数学部分,因为我认为这超出了本文的范围。仍然可以在其他地方解释(可能是另一个问题?)。
I won't explain the math part because I think it's beyond the scope of this post. Could still explain it somewhere else (another question maybe ? ).
这篇关于如何在不考虑变换的情况下计算getBoundingClientRect()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!