# 判断元素是否在可视区域内
可视区域即我们浏览网页的设备肉眼可见的区域. 常见的应用场景有:
- 图片的懒加载
- 列表的无线滚动
- 计算广告元素的曝光情况
- 可点击链接的预加载
实现的方式常见的有三种:
# Element.getBoundingClientRect()
getBoundingClientRect
返回一个DOMRect
(opens new window) 对象, 提供了元素的大小及其想对视口的位置.
示意图如下:
如果一个元素在视窗之内的话,那么它一定满足下面四个条件:
- top 大于等于 0
- left 大于等于 0
- bottom 小于等于视窗高
- right 小于等于视窗宽度
点击查看代码
/**
* 判断元素是否在可视区域内 (getBoundingClientRect)
* 如果一个元素在视窗之内的话,那么它一定满足下面四个条件:
* - top 大于等于
* - left 大于等于
* - bottom 小于等于视窗高
* - right 小于等于视窗宽度
*
* @param {HTMLElement} element
* @returns {boolean}
*/
function inViewport(element) {
const viewWidth = window.innerWidth || document.documentElement.clientWidth
const viewHeight = window.innerHeight || document.documentElement.clientHeight
const {
top, right, bottom, left,
} = element.getBoundingClientRect()
return (
top >= 0 &&
left >= 0 &&
right <= viewWidth &&
bottom <= viewHeight
)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# IntersctionObserver
Intersection Observer API 会注册一个回调函数, 每当被监视的元素进入或者退出另外一个元素时 (或者 viewport),或者两个元素的相交部分大小发生变化时, 该回调方法会被触发执行
点击查看代码
/**
* 判断元素是否在可视区域内(IntersectionObserver)
* MDN: https://developer.mozilla.org/zh-CN/docs/Web/API/IntersectionObserver
* @param {HTMLElement} element
*/
function inViewport(element) {
const observeCallback = (entries) => {
if(entries[0].isIntersecting) {
console.log('Yes, in viewport.')
} else {
console.log('No, not in viewport.')
}
}
const observer = new IntersectionObserver(observeCallback, { threshold: 1.0 })
observer.observe(element)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# offsetTop/scrollTop
这种方式受布局影响, 有些不太准确
点击查看代码
/**
* 判断元素是否在可视区域内(offsetTop scrollTop)
* 不太准确, 受布局的影响会导致判断偏差
* 公式: el.offsetTop - document.documentElement.scrollTop <= viewPortHeight
* @param {HTMLElement} element
*/
function inViewport(element) {
const viewportHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
const elOffsetTop = element.offsetTop
const docScrollTop = document.documentElement.scrollTop
const top = elOffsetTop - docScrollTop
return top <= viewportHeight
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13