不使用getBoundingClientRect的思路(解决办法请直接看使用getBoundingClientRect)
获取元素的绝对位置
思路:将元素的offsetLeft和offsetTop累加,直到body
没有清除默认样式,也就是html和body之间的margin
也就是说默认api里body.offsetleft&body.offsettop都为0
获取绝对定位时到整个窗口,如果不清楚默认样式,是到body。(一般情况下都要清除,不清楚会影响计算)
// 清除默认样式*{margin:0;padding: 0;}
如果是火狐-循环一次;如果不是火狐-循环两次
function getPointAb(node){// while循环叠加offsetParent的offsetleft和offsetTopvar x = 0;var y = 0;while(node){x += node.offsetLeft;y += node.offsetTop;node = node.offsetParent}return {x:x,y:y}}}
这样就可以得到元素的绝对定位
获取元素的相对位置
如果没有滚动条,绝对位置=相对位置(body和视口一样);
一旦出现滚动条,绝对位置≠相对位置
how to compute relative position ? 绝对位置-滚动条滚动时元素滚动的距离。
// 获取滚动条滚动距离window.onload = function(){var L = document.documentElement.scrollLeft||document.body.scrollLeft;var T = document.documentElement.scrollTop||document.body.scrollTop;console.log(L,T);}
function getPointRe(node){// while循环叠加offsetParent的offsetleft和offsetTopvar x = 0;var y = 0;while(node){x += node.offsetLeft;y += node.offsetTop;node = node.offsetParent}var L = document.documentElement.scrollLeft||document.body.scrollLeft;var T = document.documentElement.scrollTop||document.body.scrollTop;return {x:x-L,y:y-T}}}
getBoundingClientRect
相对位置
❗上述函数有一个问题——>如果有border/margin会影响函数取值,因为offsetLeft和offsetTop计算到padding。
如果给元素+border/margin,计算结果不变。
🔸使用getBoundingClientRect不受border和margin影响
// 元素border-box的尺寸 height: width:
// 元素左上角的相对位置 left: top:
// 元素右下角的相对位置 bottom: right:
左上角的相对位置(left: top:)和 元素右下角的相对位置(bottom: right: ) 算了border和margin
若想得到左下角和右上角的相对位置——>用左上角+border-box(右下角-border-box)
content-box 的 width 不包括 padding 和 border
border-box 的 width 包括 padding 和 border
getBoundingClientRect的width和height计算加了border,所以获取左下角和右上角的相对位置可以用
:左上角的相对位置+getBoundingClientRect返回的width/height
绝对位置
相对位置 + 滚动条滚动时元素滚动的距离
若有获取元素的绝对位置和相对位置的需求,首选getBoundingClientRect这个API,并且其兼容性非常高。