如何在不考虑变换的情况下计算getBoundingClientRect()? [英] How to compute getBoundingClientRect() without considering transforms?

查看:118
本文介绍了如何在不考虑变换的情况下计算getBoundingClientRect()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆