JS实现图片懒加载插件


风晓
风晓 2024-01-01 19:49:57 52508 赞同 0 反对 0
分类: 资源
JS实现图片懒加载插件

1.做成一个组件还是service?

公司框架是angular,类似于图片懒加载这类较通用的功能,肯定得保证复用性与可拓展性,同事建议做成组件,哪张图片需要懒加载给这个图片添加组件名;我心想,那repeat出来一百张图,那岂不是瞬间瞬间100个组件同时运行,内存爆炸....听起来不是很优化的感觉。想了下,还是做成service,哪里需要注入我的service,调用我提前提供好的方法即可。

 

基本功能流程图如上,提前为需要懒加载的图片统一添加lazyImg-src="真实图片地址">属性,页面加载完成获取所有有lazyImg-src属性的dom,获取dom操作只会执行一次,我不想每次滚动都会反复获取dom,这样太友好。

 页面加载完成会自调一次懒加载函数,之后就交给滚动事件触发,当一个dom元素的图片替换完成,就将此dom从数组中删除,懒加载函数执行的前置条件为dom数组不为空,那么当第一次懒加载完后无论用户怎么滚动,核心代码不会再执行。

2.如何判断图片是否在视图框内?

这个问题可以说是懒加载的核心问题,弄懂这个,功能已经做了一大半了,我们来看一个图:

 判断一张图是否在视图范围内,需要判断X轴与Y轴的进入,离开的两种情况,加起来就是四个条件,只要同时满足,则元素一定在视图范围内。

3.怎么使用?

给需要懒加载的元素添加lazyImg-src属性,里面存放真实的图片地址,为了更好的体验,你可以将图片路径设置为一张loading的图片,在懒加载时再进行替换。

调用lazyload方法,并传入视图对象,什么意思呢,比如下面给出的demo代码中,位置参照对象是window,视图对象是ul,判断的是每张img。

当触发滚动事件时,监听的是ul的滚动条,步骤如下,引入JS

先获取视图对象,例如:

const viewDom = document.querySelector('.container');

然后调用方法lazyload(viewDom )即可。

你也可以不传递视图对象,那么此时视图对象会默认为window,也就是说当触发滚动事件时,监听的是window的滚动条。

 三、实现代码

效果图,此时的滚动事件监听的是ul的滚动条。随着滚动,netWork中可以看到img在一张张加载。

 

HTML部分,图片自己准备,懒加载JS记得引入

复制代码
    <ul class="container">
        <li><img src="img/timg.gif" alt="1" lazyImg-src="img/1.jpg"></li>
        <li><img src="img/timg.gif" alt="2" lazyImg-src="img/2.jpg"></li>
        <li><img src="img/timg.gif" alt="3" lazyImg-src="img/3.jpg"></li>
        <li><img src="img/timg.gif" alt="4" lazyImg-src="img/4.jpg"></li>
        <li><img src="img/timg.gif" alt="5" lazyImg-src="img/5.jpg"></li>
        <li><img src="img/timg.gif" alt="6" lazyImg-src="img/6.jpg"></li>
        <li><img src="img/timg.gif" alt="7" lazyImg-src="img/7.jpg"></li>
        <li><img src="img/timg.gif" alt="8" lazyImg-src="img/8.jpg"></li>
        <li><img src="img/timg.gif" alt="9" lazyImg-src="img/9.jpg"></li>
        <li><img src="img/timg.gif" alt="10" lazyImg-src="img/10.jpg"></li>
    </ul>
复制代码

CSS部分:

复制代码
body{
    position:relative;
    padding:0;
    margin:0;
    display: table;
}
.container{
    list-style: none;
    height: 400px;
    width: 250px;
    overflow: auto;
    margin-top:200px;
}
.container>li{
    margin-bottom: 10px;
}
.container>li>img{
    background-color: #e4393c;
    width: 200px;
    height: 200px;
}
复制代码

JS部分,别被变量的数量吓到,搞懂原理其实真的不复杂,或者打断点跟着跑一遍。

复制代码
//处理图片懒加载
function lazyload (option) {
  //如果不传递视图对象,则默认视图对象为window
  var viewDom = option || window,
      scroll_top, //滚动条Y轴距离
      scroll_left, //滚动条X轴距离
      viewDomWidth, //视图宽
      viewDomHeight,//视图高
      viewDomLeft, //视图左偏移量
      viewDomTop, //视图上偏移量
      imgWidth, //img宽
      imgHeight, //img高
      imgLeft, //img左偏移量
      imgTop, //img上偏移量
      imgArr = [],
      doc = document.documentElement;

  //获取视图元素宽高,左上偏移量,分为window或普通dom两种情况
  if (viewDom === window) {
    viewDomWidth = doc.clientWidth; 
    viewDomHeight = doc.clientHeight;
    viewDomLeft = doc.offsetLeft;
    viewDomTop = doc.offsetTop;
  }else{
    viewDomWidth = viewDom.offsetWidth;
    viewDomHeight = viewDom.offsetHeight;
    viewDomLeft = viewDom.offsetLeft;
    viewDomTop = viewDom.offsetTop;
  };

  /**
   * @desc 将nodeList转为数组,方便操作
   * @param {object} data nodelist对象
   */
  function nodeListToArr(data) {
    var arr = [];
    try{
      //ie8及以下不支
      arr = Array.prototype.slice.call(data);
    }catch(e){
      //兼容写法
      var len = data.length;
      for(var i = 0; i < len; i++){
        arr.push(data[i]);
      }
    };
    return arr;
  };
  //取得所有需要懒加载的dom元素
  var imgNode = document.querySelectorAll("[lazyImg-src]");
  imgArr = nodeListToArr(imgNode);
  //替换路径函数,懒加载核心函数
  function replaceUrl () {
    //只有img数组不为空,才会执行替换路径的操作
    if(imgArr.length){
      var i = 0;
      //获取视图元素滚动条滚动距离
      if (viewDom === window) {
        scroll_top = doc.scrollTop;
        scroll_left = doc.scrollLeft;
      }else{
        scroll_top = viewDom.scrollTop;
        scroll_left = viewDom.scrollLeft;
      };
      //遍历需要懒加载的dom节点
      for (; i<imgArr.length; i++) {
        //获取当前元素的宽高
        imgWidth = imgArr[i].offsetWidth;
        imgHeight = imgArr[i].offsetHeight;
        //当前元素随着滚动的变化的偏移量为
        imgLeft = imgArr[i].offsetLeft - scroll_left;
        imgTop = imgArr[i].offsetTop - scroll_top;
        //横向判断是否进入视图元素
        var boundaryLeft = imgLeft + imgWidth - viewDomLeft;
        var boundaryRight = viewDomLeft + viewDomWidth - imgLeft;
        //同理纵向判断是否进入视图元素
        var boundaryTop = imgTop + imgHeight - viewDomTop;
        var boundaryBottom = viewDomTop + viewDomHeight - imgTop;
        if(boundaryLeft>0 && boundaryRight>0 && boundaryTop>0 && boundaryBottom>0) {
          //替换图片路径,添加判断,img替换src,非img替换background
          if(imgArr[i].nodeName === "IMG"){
            imgArr[i].src = imgArr[i].attributes['lazyimg-src'].value;
          }else{
            //不是图片的替换背景图
            // imgArr[i].style.backgroundImage = imgArr[i].attributes['lazyimg-src'].value;
          };
          //操作完一项就删除一项,同时重置i;
          imgArr.splice(i,1);
          i -= 1;
        };
      };
    };
  };
  //自调
  replaceUrl();
  //添加事件监听
  viewDom.addEventListener("scroll",replaceUrl);
};
//测试调用,默认绑定window,或传递你需要监听的dom对象,调用就2步
var container = document.querySelector(".container");
lazyload(container);
复制代码

如果您发现该资源为电子书等存在侵权的资源或对该资源描述不正确等,可点击“私信”按钮向作者进行反馈;如作者无回复可进行平台仲裁,我们会在第一时间进行处理!

评价 0 条
风晓L1
粉丝 1 资源 2038 + 关注 私信
最近热门资源
银河麒麟桌面操作系统备份用户数据  130
统信桌面专业版【全盘安装UOS系统】介绍  128
银河麒麟桌面操作系统安装佳能打印机驱动方法  120
银河麒麟桌面操作系统 V10-SP1用户密码修改  108
麒麟系统连接打印机常见问题及解决方法  27
最近下载排行榜
银河麒麟桌面操作系统备份用户数据 0
统信桌面专业版【全盘安装UOS系统】介绍 0
银河麒麟桌面操作系统安装佳能打印机驱动方法 0
银河麒麟桌面操作系统 V10-SP1用户密码修改 0
麒麟系统连接打印机常见问题及解决方法 0
作者收入月榜
1

prtyaa 收益393.62元

2

zlj141319 收益218元

3

1843880570 收益214.2元

4

IT-feng 收益210.13元

5

风晓 收益208.24元

6

777 收益172.71元

7

Fhawking 收益106.6元

8

信创来了 收益105.84元

9

克里斯蒂亚诺诺 收益91.08元

10

技术-小陈 收益79.5元

请使用微信扫码

加入交流群

请使用微信扫一扫!