Intersection observer检测元素是否在视窗内

前言

一直以来,检测元素在浏览器视窗口内不是件容易的事,很多解决方案都不能很准确的判断,计算量也有可能拖慢网站性能。
但是很多场景都需要用到:

  • 当页面滚动时,懒加载图片或其他内容。
  • 实现“可无限滚动”网站,也就是当用户滚动网页时直接加载更多内容,无需翻页。
  • 为计算广告收益,检测其广告元素的曝光情况。
  • 根据用户是否已滚动到相应区域来灵活开始执行任务或动画。

通常检测是否在视窗内原理

监听浏览器滚动事件scroll,对每个目标元素执行Element.getBoundingClientRect(),getBoundingClientRect方法返回元素的大小及其相对于视口的位置。 此方法可获取整个网页左上角定位 ,及距浏览器顶部的或左侧的距离,然后用innerHeightinnerwidth等得到视窗大小,以此相减来判断是否在视窗范围内。

具体代码如下:https://codepen.io/raoenhui/pen/BGBYpX

还有其他检测原理大多都是通过计算得到,但是下面我将要介绍由浏览器自带方法检测元素是否在视窗内。

新检测原理Intersection observer

Intersection observer 允许你配置一个回调函数,每当target进入浏览器视窗时,触发回调函数。

example1.gif

源码地址:https://codepen.io/raoenhui/pen/XoVEjK

用法

var options = {
    root: document.querySelector('#scrollArea'), 
    rootMargin: '0px', 
    threshold: 1.0
}
var callback = function(entries, observer) { 
    /* Content excerpted, show below */ 
};
var observer = new IntersectionObserver(callback, options);

参数

options 配置项

  • root 目标元素。默认使用浏览器视口做为root
  • rootMargin root元素的外边距。
  • threshold 阈值。可以是单一的number也可以是number数组,一般取1。

callback 回调函数

案例

example.gif

源码地址:https://codepen.io/raoenhui/pen/xQKPaK

target元素和root元素相交程度达到该值的时候IntersectionObserver注册的回调函数将会被执行。
如果你只是想要探测当target元素的在root元素中的可见性超过50%的时候,你可以指定该属性值为0.5。如果你想要target元素在root元素的可见程度每多25%就执行一次回调,那么你可以指定一个数组[0, 0.25, 0.5, 0.75, 1]。默认值是0(意味着只要有一个target像素出现在root元素中,回调函数将会被执行)。该值为1.0含义是当target完全出现在root元素中时候 回调才会被执行。

插件jquery_lazyload懒加载就是用到了此方法,

源码地址:https://github.com/tuupola/jquery_lazyload

 this.observer = new IntersectionObserver(function(entries) {
                entries.forEach(function (entry) {
                    if (entry.intersectionRatio > 0) {
                        self.observer.unobserve(entry.target);
                        let src = entry.target.getAttribute(self.settings.src);
                        let srcset = entry.target.getAttribute(self.settings.srcset);
                        if ("img" === entry.target.tagName.toLowerCase()) {
                            if (src) {
                                entry.target.src = src;
                            }
                            if (srcset) {
                                entry.target.srcset = srcset;
                            }
                        } else {
                            entry.target.style.backgroundImage = "url(" + src + ")";
                        }
                    }
                });
            }, observerConfig);

兼容性

兼容性chrome基本支持,但是意外的是safari支持性不好,用到的小伙伴们要注意这点了,兼容性具体看下图:

image.png

另外发现微信小程序也用了IntersectionObserver哦,但是有个小问题当页面滑动太快IntersectionObserver会漏监听,小程序使用文档为https://developers.weixin.qq.com/miniprogram/dev/api/IntersectionObserver.html

其他链接

Happy coding .. :)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 第一部分 HTML&CSS整理答案 1. 什么是HTML5? 答:HTML5是最新的HTML标准。 注意:讲述HT...
    kismetajun阅读 27,802评论 1 45
  • 特别声明:此篇文章内容来源于@Jeremy Wagner的《Lazy Loading Images and Vid...
    Naeco阅读 30,725评论 0 32
  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 13,815评论 1 92
  • 第3章 基本概念 3.1 语法 3.2 关键字和保留字 3.3 变量 3.4 数据类型 5种简单数据类型:Unde...
    RickCole阅读 5,168评论 0 21
  • 1、感恩自己煮了喜欢吃的素饺子,还配了黄桃罐头,美美哒早餐。 2、感恩与小伙伴们分享龚琳娜老师教唱歌的课程音频,还...
    感恩的罗莉阅读 291评论 0 0