JQ的offset().top与JS的getBoundingClientRect区别详解,JS获取元素距离视窗顶部可变距离
壹 ❀ 引
我在 JQ的offset().top与js的offsetTop区别详解 这篇博客中详细分析了JQ方法offset().top与JS属性offsetTop的区别,并得出了一条offset().top = offsetTop - scrollTop的结论,不过此结论只适用于监听元素滚动条,而window的滚动条并不满足。那么在滚动window滚动条时如何获取元素距离视窗顶部的距离呢,这就不得说说本文的主角getBoundingClientRect方法。
贰 ❁ 关于getBoundingClientRect()
我们可以先拷贝下面的代码,动手起来跟着操作一遍,印象会深刻,需要引入JQ,这里提供一个静态资源地址,进去搜索JQ直接复制地址引入即可:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" href="css/demo.css">
</head>
<body>
<div class="child"></div>
</body>
<script src="https://cdn.staticfile.org/jquery/3.4.1/jquery.js"></script>
<script src="js/app.js"></script>
</html>
* {
padding:;
margin:;
list-style: none;
outline: none;
}
.child {
margin-top: 200px;
margin-left: 200px;
height: 200px;
width: 200px;
background: #bbded6;
border: 5px solid #8ac6d1;
}
// JS getBoundingClientRect()
let child = document.querySelector('.child');
console.log(child.getBoundingClientRect()); //JQ offset()
// let son = $('.child');
// son.offset(); // JS offsetTop
// child.offsetTop;
这里我们在页面定义了一个宽高各200px且包含5px边框的盒子,由于没设置box-size = ’border-box'属性,所以盒子总宽高为210px,这里我们直接打印出getBoundingClientRect方法结果,如下:

可以看到getBoundingClientRect()返回了一个 DOMRect 对象,该对象包含了元素多个属性,其中最显眼的width与height毫无悬念就是元素宽高,除此之外还包含top,bottom,right,left与x,y属性。
不难猜出,top和left为元素左上顶点距离视窗顶端与左侧距离,而right与bottom为右下顶点距离视窗左侧与顶端距离。而x与left一致,y与top一致。

现在修改代码,将css中的margin-top修改为1000px,同时使用scroll事件打印getBoundingClientRect的top值与滚动条距离,其它不变,像这样:
window.onscroll = function () {
//输出top值与滚动条距离
console.log(child.getBoundingClientRect().top, document.documentElement.scrollTop);
};
当滚动条滚动,可以发现getBoundingClientRect().top值加上document.documentElement.scrollTop的值终等于1000,而这1000正是元素距离视窗顶部的距离。

现在将JQ的代码与输出offsetTop的代码取消注释,并加入到scroll事件中,再次滚动滚动条像这样:
// JS getBoundingClientRect()
let child = document.querySelector('.child');
let son = $('.child');
window.onscroll = function () {
//输出getBoundingClientRect的top值,JQ的offset().top与offsetTop
console.log(child.getBoundingClientRect().top,son.offset().top,child.offsetTop);
};

可以看到getBoundingClientRect().top是顺着滚动条下移慢慢变小的,毕竟元素距离视窗顶部越来越近了,而offset().top与offsetTop一直保持1000,为什么呢?
首先,我们知道offsetTop获取的是元素距离自己最近的offsetParent(position为非static且距离自己最近的祖先元素)的距离,且这个距离不随滚动条滚动变化,也就是说这个距离开始是多少就是多少,是个恒定值。
而JQ的offset().top获取的是元素距离文档顶端的距离。怎么去理解这个文档呢,我们把浏览器网页可读范围比喻成一幅画,这幅画包含了html,所以如果html内容越多(比如给html设置上margin),这幅画就会越长;而视窗呢可以比喻成一块玻璃,我们透过玻璃看这幅画,如果画的高度比玻璃还高那就有了滚动条,当滚动往下拉时,等同于玻璃位置不变,但是画会往上移。
知道这个概念后,我们再来想想上面例子为什么offset().top一直不变,当滚动条下拉,画往上移,而画中的元素是随着画一起运动的,很明显该元素相对画顶端的距离也一直没变,这下总知道为啥是1000了吧。
而getBoundingClientRect获取的是元素距离视窗顶端的距离,当画上移,元素肯定距离视窗顶端越来越近,所以这个距离一定越来越小。
叁 ✿ getBoundingClientRect与offset().top的区别
那么到这,我们知道了getBoundingClientRect参照是视窗顶端,而JQ的offset().top参照的是文档,两者参照对象不同。
当监听的是window的滚动条时,元素的getBoundingClientRect().top会原来越小,而offset().top一直不变。
当监听某个元素的滚动条时,元素的getBoundingClientRect().top会与offset().top保持一致,比如我让一个ul包含了多个li,滚动ul的滚动条时,获取第一个li的相关属性,有兴趣可以将下面的代码替换一下:
HTML
<ul>
<li style="background: orange;">1</li>
<li style="background: black;">2</li>
<li style="background: blueviolet;">3</li>
<li style="background: pink;">4</li>
</ul> CSS
* {
padding: 0;
margin: 0;
list-style: none;
outline: none;
box-sizing: border-box;
} ul {
width: 200px;
height: 100px;
overflow-y: scroll;
margin: 100px; } li {
width: 100px;
height: 300px;
line-height: 300px;
text-align: center;
} JS
let parent = document.querySelector('ul');
let child = document.querySelectorAll('li')[0];
parent.onscroll = function () {
//输出getBoundingClientRect的top值,JQ的offset().top与offsetTop
console.log(child.getBoundingClientRect().top, $(child).offset().top, child.offsetTop);
};

可以看到getBoundingClientRect().top与offset().top的值完全一致。
肆 ❤ 获取元素距离距离视窗顶部的可变距离
楼层导航,懒加载,返回顶部按钮等等,只要涉及scroll事件,都无法避免的要去计算某个元素距离视窗顶部的距离,经过前文的分析,不管是监听window滚动条还是元素滚动条,其实都有两种可行方法。
如果是监听的是window的滚动条,那么可以使用:
window.onscroll = function () {
可变距离 = document.querySelector('元素').getBoundingClientRect().top
};
其次可以获取元素的offsrtTop减去滚动条距离,前提是得保证元素的offsetParent为html元素或者body:
var offsetTop = document.querySelector('元素').offsetTop;
window.onscroll = function () {
可变距离 = offsetTop - document.documentElement.scrollTop;
};
如果监听的是元素的滚动条,获取元素内子元素距离视窗的高度可以使用JQ的offset().top:
document.querySelector('父元素').onscroll = function () {
子元素可变距离 = $('子元素元素').offset().top;
};
其次可以使用子元素的offsetTop减去父元素滚动条距离,当然你也得保证子元素的offsetParent为html或body:
var parent = document.querySelector('父元素');
var son = document.querySelector('子元素');
parent.onscroll = function () {
子元素可变距离 = son.offsetTop - parent.scrollTop;
};
伍 ☸ 总
那么结合文章开头的另一篇博客以及本文,我们详细介绍了JQ的offset().top与JS的offsetTop以及getBoundingClientRect的区别:
我们知道了offset().top参照对象是文档上边界,当监听window滚动条,它的效果与offsetTop类似,都是固定不变的值,毕竟在元素上移时,整体的文档也上移了。
我们知道offsetTop的参照对象是一个可变的offsetParent,而且得到的值永远不变。
我们还知道了好用的getBoundingClientRect方法,它的参照对象是视窗顶端,不管滚动条是window还是元素的,我们可以时时拿到可变尺寸。
当然我们还了解了特定情况下,使用offsetTop - scrollTop一样能拿到这个可变值。
那么到这里,本文结束。
JQ的offset().top与JS的getBoundingClientRect区别详解,JS获取元素距离视窗顶部可变距离的更多相关文章
- JQ的offset().top与js的offsetTop区别详解
一.前言 最近在做一个图片懒加载的插件,就纵轴(Y轴)而言,我需要时时获取图片的上偏移量,好判断是否已进入视图区域,而我所理解的是offsetTop应该是跟offset().top一样的,然后陷入了因 ...
- js获取元素到屏幕左上角的距离
开发过程中经常会遇到 获取元素到屏幕左上角的距离, 当我们使用jQuery开发时,我们可以使用 $.offset()来获取准确的距离. 如果我们的项目中并没有引入jQuer的话,跟希望通过原生方法实现 ...
- 详解js变量、作用域及内存
详解js变量.作用域及内存 来源:伯乐在线 作者:trigkit4 原文出处: trigkit4 基本类型值有:undefined,NUll,Boolean,Number和Strin ...
- [转]javascript console 函数详解 js开发调试的利器
javascript console 函数详解 js开发调试的利器 分步阅读 Console 是用于显示 JS和 DOM 对象信息的单独窗口.并且向 JS 中注入1个 console 对象,使用该 ...
- js调试工具Console命令详解
这篇文章主要介绍了js调试工具Console命令详解,需要的朋友可以参考下 一.显示信息的命令 复制代码 代码如下: < !DOCTYPE html> < html> &l ...
- 详解js和jquery里的this关键字
详解js和jquery里的this关键字 js中的this 我们要记住:this永远指向函数运行时所在的对象!而不是函数被创建时所在的对象.this对象是在运行时基于函数的执行环境绑定的,在全局环境中 ...
- 详解js的bind、call、apply
详解js的bind.call.apply 说明 虽然bind.call.apply都是js很基础的一块知识,但是我从未认真总结过这三者的区别. 由于公司后端是用的微服务架构,又没有中间层对接,导致前端 ...
- 详解js面向对象编程
转自:http://segmentfault.com/a/1190000000713346 基本概念 ECMA关于对象的定义是:”无序属性的集合,其属性可以包含基本值.对象或者函数.“对象的每个属性或 ...
- jquery的offset().top与javascript的offsetTop区别?
offset().top是jquery的方法,需引入jquery,它获取你绑定元素上边框相对于html上边界的偏移量 offsetTop是原生js的方法,它获取你绑定元素上边框相对于离自己最近且pos ...
随机推荐
- JS基础-DOM
DOM DOM 事件的级别 DOM 事件模型 DOM 事件流 DOM 事件捕获的具体流程 Event 对象的常见应用 自定义事件 DOM概述 | MDN DOM | MDN DOM操作 DOM事件级别 ...
- eclipse右下角一直在loading jar文件,如何关闭?
通常导入项目的时候,右下角会显示download一些jar包或者其它内容,速度非常慢,如果你长得很帅很美可能更拖网速,最后可能会超时报错. 大招来了!!! 首先,打开windows->pre ...
- 【docker】Dockerfile
[docker]Dockerfile 转载: ============================================================= =============== ...
- xshell连接问题记录
操作系统Ubuntu 18.04 安装ubuntu后,连接不上.ubuntu18会每次重启重写dns,导致每次开机ip地址都不一样,所以需要先固定IP ubuntu18.04固定ip 修改固定 IP ...
- webpack打包出现WARNING in configuration The 'mode' option has not been set, webpack will fallback to 'production' for this value. 错误
打包运行的时候出现以下错误 WARNING in configurationThe 'mode' option has not been set, webpack will fallback to ' ...
- 现代前端库开发指南系列(二):使用 webpack 构建一个库
前言 在前文中,我说过本系列文章的受众是在现代前端体系下能够熟练编写业务代码的同学,因此本文在介绍 webpack 配置时,仅提及构建一个库所特有的配置,其余配置请参考 webpack 官方文档. 输 ...
- Ansible-playbook之循环判断
1.循环 (loop) # 使用循环创建硬连接:x连接到y:z连接到k: - hosts: web - name: Create two hard links file: src: "{{ ...
- 关于独显A卡利用率一直是0不运行的问题
情况: 独显一直是0,玩游戏时核显,也就是GPU-0快满了GPU-1也是0,跟没有一样,怀疑自己买电脑的时候是不是被骗了. 在高级电源选项中,有个可切换动态显卡->全局设置的选项,设置成最大化性 ...
- Open Redirect 开放重定向
- WebShell代码分析溯源(十一)
WebShell代码分析溯源(十一) 一.一句话变形马样本 <?php $e = $_REQUEST['e'];declare(ticks=1);register_tick_function ( ...