[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为空的时候才是绝对的视窗。