[jQuery]判断元素是否进入视窗
网页开发的时候,常常需要了解某个元素是否进入到"视口"(viewport),即用户在当前屏幕内是否看到这个元素
上图的绿色方块不断滚动,顶部会提示它的可见性。
思路 一
监听窗口 scroll 事件后,调用目标元素的 getBoundingClientRect() 方法, 获得该元素相对于视口左上角的坐标,然后在判断是否在视口内部。
这个方法的缺点是,由于 scroll 事件密集发生,容易造成性能问题;
//视口的高度
winHeight = $(window).height();
// 元素顶部相对坐标
elTop = object.getBoundingClientRect().top
//元素底部相对坐标
elBottom = object.getBoundingClientRect().top
if( elTop < winHeight && elBottom > 0 ){
// 看得见
}else{
// 看不见
}
Demo
思路 二、
1. API
利用浏览器原生提供的构造函数 IntersectionObserver ,
var io = new IntersectionObserver(callback, option);
callback是可见性变化时的回调函数,option是配置对象(该参数可选)。
构造函数的返回值是一个观察器实例。实例的observe方法可以指定观察哪个 DOM 节点。
// 开始观察
io.observe(document.getElementById('example'));
// 停止观察
io.unobserve(element);
// 关闭观察器
io.disconnect();
上面代码中,observe 的参数是一个 DOM 节点对象。如果要观察多个节点,就要多次调用这个方法
io.observe(elementA); io.observe(elementB);
2. callback参数
目标元素的可见性发生变化,就会调用观察期的回调函数 callback ,即 刚刚能看见元素 和 完全看不到元素的时候 都会触发回调函数
var io = new IntersectionObserver(
entries => {
console.log(entries);
}
);
entries 是 回调函数的参数,它的类型是数组, 数组的每个成员都是一个IntersectionObserverEntry对象。
简单来说, 如果同时有两个被观察的对象的可见性发生变化,entries数组就会有两个成员。
3. IntersectionObserverEntry 对象
IntersectionObserverEntry对象提供目标元素的信息,一共有七个属性。
{
// time:可见性发生变化的时间,是一个高精度时间戳,单位为毫秒
time: 3893.92,
// 根元素的矩形区域的信息,getBoundingClientRect()方法的返回值,如果没有根元素(即直接相对于视口滚动),则返回null
rootBounds: ClientRect {
bottom: 920,
height: 1024,
left: 0,
right: 1024,
top: 0,
width: 920
},
// 目标元素的矩形区域的信息
boundingClientRect: ClientRect {
// ...
},
// 目标元素与视口(或根元素)的交叉区域的信息
intersectionRect: ClientRect {
// ...
},
// 被观察的目标元素,是一个 DOM 节点对象
target: element,
// 目标元素当前是否可见 Boolean值 可见为true
isIntersecting: true,
// 目标元素的可见比例,即intersectionRect占boundingClientRect的比例,完全可见时为1,完全不可见时小于等于0
intersectionRatio: 0.54
}
4. 判断元素是否进入视窗
var io = new IntersectionObserver(function (entries) {
entries.forEach(function (item) {
var el = item.target;
if (item.isIntersecting) {
// 看得见
// 停止观察
io.unobserve(el);
} else {
// 看不见
}
})
});
Demo
5. Option 对象
threshold 属性
threshold属性决定了什么时候触发回调函数。它是一个数组,每个成员都是一个门槛值,默认为[0],即交叉比例(intersectionRatio)达到0时触发回调函数。
new IntersectionObserver( entries => {
/* ... */
}, {
threshold: [0, 0.25, 0.5, 0.75, 1]
}
);
表示当目标元素 0%、25%、50%、75%、100% 可见时,会触发回调函数。
root 属性
用于观察的根元素,默认是浏览器的视口,也可以指定具体元素,指定元素的时候用于观察的元素必须是指定元素的子元素
rootMargin
用来扩大或者缩小视窗的的大小,使用css的定义方法,10px 10px 30px 20px 表示top、right、bottom 和 left的值
new IntersectionObserver( entries => {
/* ... */
}, {
root: document.querySelector('.box'),
rootMargin: '30px 100px 20px'
}
);
蓝线就是咱们定义的root元素,我们添加了rootMargin属性,将视窗的增大了,虚线就是现在的视窗,所以元素现在也就在视窗里面了。
由此可见,root元素只有在rootMargin为空的时候才是绝对的视窗。