获取html元素的位置,如何获取页面元素的位置

背景:最近在商品列表项目迭代中,需要在商品列表底部增加一个分销商品广告位,另外接收到一个产品曝光度的埋点需求,需要知道产品出现在用户视口后在进行数据统计!

基于虚拟 DOM 数据驱动的思想,最不提倡的就是 jquery 时代的 DOM 操作!但是在目前一些复杂的页面中经常还是会用 javascript 处理一些 DOM 元素,实现一些动态效果;最常见的是用到一些元素的位置和尺寸的计算,但是其中浏览器的兼容性问题也是不可忽略的一部分,要想写出预想效果的JavaScript代码,我们需要了解一些基本知识。

基本概念

网页大小:一张网页的全部面积,就是它的大小。通常情况下,网页的大小由内容和 CSS 样式表决定。

浏览窗口大小:指的是在浏览器窗口中看到的那部分网页面积,又叫做 viewport (视口)。

如果网页的内容能够在浏览器中全部显示(也就不出现滚动条),那么网页的大小和浏览器窗口的大小是相等的。如果不能全部显示,则滚动浏览器窗口,可以显示出网页的各个部分。

基本元素属性

在每个HTML元素都有下列属性。

offsetWidth

clientWidth

scrollWidth

offsetHeight

clientHeight

scrollHeight

offsetLeft

clientLeft

scrollLeft

offsetTop

clientTop

scrollTop

为了理解方便这些属性,我们需要知道 HTML 元素的实际内容有可能比分配用来容纳内容的盒子更大,因此可能会出现滚动条,内容区域是视口,当实际内容比视口大的时候,需要把元素的滚动条位置考虑进去。

clientHeight 和 clientWidth 用于描述元素内尺寸,是指元素内容+内边距大小,不包括边框(IE下实际包括)、外边距、滚动条部分

offsetHeight 和 offsetWidth 用于描述元素外尺寸,是指元素内容+内边距+边框,不包括外边距和滚动条部分

clinetTop 和 clinetLeft 返回内边距的边缘和边框的外边缘之间的水平和垂直距离,也就是左,上边框宽度

offsetTop 和 offsetLeft 表示该元素的左上角(边缘外边框)与已定位的父容器(offsetParent对象)左上角的距离

offsetParent 对象是指元素最近的定位(relative、absolute)祖先元素,递归上溯,如果没有祖先元素是定位的话,会返回 null

获取视口大小

网页上的每个元素,都有 clientHeight 和 clientWidth属性。这两个属性指元素的内容部分再加上 padding 的所占据的视觉面积,不包括 border 和滚动条占用空间。

9abbcb113d637e29a4ec5a15246011f3.png

因此,document 元素的 clientHeight 和 clientWidth 属性,就代表了网页的大小

function getViewport(){

if(!document) {

return {}

}

if (document.compatMode === 'BackCompat') {

return {

width: document.body.clientWidth,

height: document.body.clientHeight

};

}

return {

width: document.documentElement.clientWidth,

height: document.documentElement.clientHeight

};

}

复制代码

上面的 getViewport 函数就是可以返回浏览器窗口的高和宽。使用的时候,有三个地方需要注意:

该函数必须在页面加载完成后才能运行,否则 document 对象还没有生成,浏览器会报错。

大多数情况下,都是 document.documentElement.clientWidth 返回正确值。但是,在 IE6 的 quirks 模式中, document.body.clientWidth 返回正确的值,因此函数中加入了对文档模式的判断

clientWidth 和 clientHeight 都是只读属性,不能对它们赋值。

获取视口大小的另一种方式

网页中的每一个元素还有 srcollHeight 和 scrollWidth 属性,指包含滚动在内的该元素的视觉面积。

那么,document 对象的 scrollHeight 和 scrollWidth 属性就是网页的大小,意思就是滚动条滚过的所有长度和宽度。

仿照 getViewport 函数,可以写出 getPagearea() 函数。

function getPagearea(){

 if (document.compatMode == 'BackCompat') {

  return {

    width: Math.max(document.body.scrollWidth, document.body.clientWidth),

    height: Math.max(document.body.scrollHeight, document.body.clientHeight)

};

 }

 return {

width: Math.max(document.documentElement.scrollWidth, document.documentElement.clientWidth),

 height: Math.max(document.documentElement.scrollHeight, document.documentElement.clientHeight)

  };

}

复制代码

相对文档与视口的坐标

当我们在计算一个 DOM 元素位置也就是坐标的时候,会涉及到两种坐标系, 文档坐标__和__视口坐标。

我们经常用到的document就是整个页面部分,而不仅仅是窗口可见部分,还包括因为窗口大小限制而出现滚动条的部分,它的左上角就是我们所谓相对于文档坐标的原点。

视口是显示文档内容的浏览器的一部分,它不包括浏览器外壳(菜单,工具栏,状态栏等),也就是当前窗口显示页面部分,不包括滚动条。

如果文档比视口小,说明没有出现滚动,文档左上角和视口左上角相同,一般来讲在两种坐标系之间进行切换,需要加上或减去滚动的偏移量(scroll offset)。

为了在坐标系之间进行转换,我们需要判定浏览器窗口的滚动条位置。window对象的pageXoffset和pageYoffset提供这些值,IE 8及更早版本除外。也可以通过scrollLeft和scrollTop属性获得滚动条位置,正常情况下通过查询文档根节点(document.documentElement)来获得这些属性值,但在怪异模式下必须通过文档的body上查询。

7bb31df3b4d63c31418fb62dfa807ee9.png

文档坐标

任何HTML元素都拥有offectLeft和offectTop属性返回元素的X和Y坐标,对于很多元素,这些值是文档坐标,但是对于以定位元素后代及一些其他元素(表格单元),返回相对于祖先的坐标。我们可以通过简单的递归上溯累加计算

function getElementPosition(e){

let x = 0;

let y = 0;

while (e != null) {

x += e.offsetLeft;

y += e.offsetTop;

e = e.offsetParent;

}

return { x, y };

}

复制代码

尽管如此,这个函数也不总是计算正确的值,当文档中含有滚动条的时候这个方法就不能正常工作了,我们只能在没有滚动条的情况下使用这个方法,不过我们用这个原理算出一些元素相对于某个父元素的坐标。

快速方法:

网页元素的相对位置就是:

let X = element.getBoundingClientRect().left;

let Y = element.getBoundingClientRect().top;

复制代码

视口坐标

计算视口坐标就相对简单了很多,可以通过调用元素的getBoundingClientRect方法。方法返回一个有left、right、top、bottom属性的对象,分别表示元素四个位置的相对于视口的坐标。getBoundingClientRect所返回的坐标包含元素的内边距和边框,不包含外边距。兼容性很好,非常好用

function getElementViewTop(element){

let actualTop = element.offsetTop;

let current = element.offsetParent;

let elementScrollTop;

while (current !== null) {

actualTop += current.offsetTop;

current = current.offsetParent;

}

if (document.compatMode == 'BackCompat') {

elementScrollTop = document.body.scrollTop;

} else {

elementScrollTop = document.documentElement.scrollTop;

}

return actualTop - elementScrollTop;

}

function getElementViewLeft(element){

let actualLeft = element.offsetLeft;

let current = element.offsetParent;

let elementScrollLeft;

while (current !== null) {

actualLeft += current.offsetLeft;

current = current.offsetParent;

}

if (document.compatMode == 'BackCompat') {

elementScrollLeft = document.body.scrollLeft;

} else {

elementScrollLeft = document.documentElement.scrollLeft;

}

return actualLeft - elementScrollLeft;

}

复制代码

快速方法:

使用 getboundingClientRect() 方法。它返回一个对象,其中包含了 left 、 top 、 width 、 height 等属性。

let X = element.getBoundingClientRect().left;

let Y = element.getBoundingClientRect().top;

复制代码

再加上滚动 距离,就可以得到绝对位置:

const X= element.getBoundingClientRect().left+document.documentElement.scrollLeft;

const Y =element.getBoundingClientRect().top+document.documentElement.scrollTop;

复制代码

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值