ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

图片懒加载

2021-03-23 14:59:48  阅读:123  来源: 互联网

标签:function el img src 加载 imgs document 图片


图片懒加载的集中实现方式

1.基于原生 js 实现图片懒加载

首先需要知道几个高度:

(1)document.documentElement.clientHeight

function getWindowHeight() {
            var windowHeight = 0;
            if (document.compatMode == "CSS1Compat") {
                windowHeight = document.documentElement.clientHeight;
            } else {
                windowHeight = document.body.clientHeight;
            }
            return windowHeight;
        }

获取屏幕可视区域的

(2)element.offsetTop

获取元素相对于文档顶部的高度。

(3)

document.documentElement.scrollTop

获取浏览器窗口顶部与文档顶部之间的距离,也就是滚动条滚动的距离。

然后滑动执行下面的方法:

var imgs = document.querySelectorAll('img');

        //offsetTop是元素与offsetParent的距离,循环获取直到页面顶部
        function getRealTop(e) {
            var realTop = e.offsetTop;
            while(e = e.offsetParent) {
                realTop += e.offsetTop;
            }
            return realTop;
        }

        function lazyLoad(imgs) {
            var H = document.documentElement.clientHeight;//获取可视区域高度
            var S = document.documentElement.scrollTop || document.body.scrollTop;
            for (var i = 0; i < imgs.length; i++) {
                if (H + S > getRealTop(imgs[i])) {
                    imgs[i].src = imgs[i].getAttribute('data-src');
                }
            }
        }

        window.onload = window.onscroll = function () { //onscroll()在滚动条滚动的时候触发
            lazyLoad(imgs);
        }

2.基于 getBoundingClientRect()实现图片懒加载

getBoundingClientRect()用于获得页面中某个元素的左,上,右和下分别相对浏览器视窗的位置。getBoundingClientRect()DOM元素到浏览器可视范围的距离(不包含页面看不见的部分)。该函数返回一个rectObject对象,该对象有 6 个属性:topleftbottomrightwidthheight;这里的topleftcss中的理解很相似,widthheight是元素自身的宽高,但是rightbottomcss中的理解有点不一样。right是指元素右边界距窗口最左边的距离,bottom是指元素下边界距窗口最上面的距离。

通过这个 API,我们就很容易获取img元素相对于视口的顶点位置rectObject.top,只要这个值小于浏览器的高度window.innerHeight就说明进入可视区域:

function isInSight(el){
  const bound = el.getBoundingClientRect();
  const clientHeight = window.innerHeight;
  return bound.top <= clientHeight;
}

实现代码:

function loadImg(el){
 if(!el.src){
   const source = el.getAttribute('data-src');;
   el.src = source;
 }
}
function checkImgs(){
  const imgs = document.querySelectorAll('img');
  Array.from(imgs).forEach(el =>{
    if (isInSight(el)){
      loadImg(el);
    }
  })
}
window.onload = function(){
  checkImgs();
}
document.onscroll = function () {
  checkImgs();
}

3.基于 IntersectionObserver 实现图片懒加载

图片

我们在平时的开发中,常常需要了解某个元素是否进入了"视口"(viewport),即用户能不能看到它

上图的绿色方块不断滚动,顶部会提示它的可见性。

传统的实现方法是,监听到scroll事件后,调用目标元素(绿色方块)的getBoundingClientRect()方法,得到它对应于视口左上角的坐标,再判断是否在视口之内。这种方法的缺点是,由于scroll事件密集发生,计算量很大,容易造成性能问题。

目前有一个新的 IntersectionObserver API,可以自动"观察"元素是否可见,Chrome 51+ 已经支持。由于可见(visible)的本质是,目标元素与视口产生一个交叉区,所以这个 API 叫做交叉观察器

var io = new IntersectionObserver(callback, option);

上面代码中,IntersectionObserver是浏览器原生提供的构造函数,接受两个参数:callback是可见性变化时的回调函数,option是配置对象(该参数可选)。

构造函数的返回值是一个观察器实例。实例的observe方法可以指定观察哪个 DOM 节点。

// 开始观察
io.observe(document.getElementById('container'));

// 停止观察
io.unobserve(element);

// 关闭观察器
io.disconnect();

上面代码中,observe的参数是一个 DOM 节点对象。

如果要观察多个节点,就要多次调用这个方法。

io.observe(elementA);
io.observe(elementB);

代码实现:

const imgs = document.querySelectorAll('img') //获取所有待观察的目标元素
var options = {}
function lazyLoad(target) {
  const observer = new IntersectionObserver((entries, observer) => {
    entries.forEach(entrie => {
      if (entrie.isIntersecting) {
        const img = entrie.target;
        const src = img.getAttribute('data-src');
        img.setAttribute('src', src)
        observer.unobserve(img); // 停止监听已开始加载的图片
      }

    })
  }, options);
  observer.observe(target)
}

imgs.forEach(lazyLoad)

4.img.loading=lazy

最后这种相对就简单很多了,它是 Chrome 自带的原生 lazyload 属性。其实支持程度还不是特别好,我们你的应用对于浏览器兼容性要求比较高的话,建议还是先观望一波~

使用方法很简单:

<img src="example.jpg" loading="lazy" alt="">

 

标签:function,el,img,src,加载,imgs,document,图片
来源: https://blog.csdn.net/qq_36893984/article/details/115121346

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有