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

 

 

posted @ 2021-02-23 22:09  阳癫疯  阅读(679)  评论(0编辑  收藏  举报