瀑布流和懒加载

瀑布流和懒加载

瀑布流

案例:瀑布流图片加载。

分析:将图片放入规定的列中,先进行图片预加载,每次放入图片时判断哪列的高度最小,然后将图片放到高度最小的列中。
如果是自适应页面,需要监听浏览器尺寸改变事件(resize),修改已经加载的列和图片的宽度,当浏览器出现滚动条。body的宽度改变,也需要修改已经加载的列和图片的宽度。

注:将代码复制到编辑器里,格式化文档看起来会方便一些,可以自己存一些图片,图片的命名和路径修改下(修改n和src即可)

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    body {
      margin: 0;
      padding: 0;
    }

    ul {
      list-style: none;
      margin: 0;
      padding: 0;
    }

    ul::after {
      content: "";
      height: 0;
      clear: both;
      overflow: hidden;
      visibility: hidden;
      display: block;
    }

    li {
      float: left;
    }
  </style>
</head>

<body>
  <ul></ul>

  <script>
    //定义有多少列COL,列宽度COL
    const COL = 5,
      GAP = 10;
    //将每一列放入liList数组,
    //将每列的高度放入heightList数组,每次判断最小高度放入图片,
    //n表示起始图片名的(2-79)
    var liList = [], heightList = [], n = 2;
    //定义每列的宽度,定义bodyWidth来记录初始可视窗口的宽度
    var width, bodyWidth;
    init();
    function init() {
      //获取可视窗口的宽度
      bodyWidth = document.body.clientWidth;
      //求出每列的宽度
      width = (bodyWidth - GAP * (COL - 1)) / COL;
      var frag = document.createDocumentFragment();
      //根据COL创建列
      for (var i = 0; i < COL; i++) {
        var li = document.createElement("li");
        //设置li的样式
        Object.assign(li.style, {
          width: width + "px",
          marginLeft: i === 0 ? "0px" : GAP + "px"
        });
        //每创建一列,将创建好的li放入liList数组中
        liList.push(li);
        //每创建一列,将heightList中数组对应的高度初始化为0
        heightList.push(0);
        //每创建一列,将创建好的列放入碎片容器frag中
        frag.appendChild(li);
      }
      //将碎片容器frag放入到页面ul中
      document.querySelector("ul").appendChild(frag);
      //执行预加载图片函数
      loadImg();
      //添加浏览器尺寸改变事件,当浏览器宽度改变,重新计算width
      window.addEventListener("resize",resize);
      //懒加载:添加滚动条滚动事件,当滚动条滚动时,继续加载后三屏的内容
      window.addEventListener("scroll",scrollHandler);
    }

    //预加载图片函数
    function loadImg() {
      //创建图片
      var img = new Image();
      //添加图片路径
      img.src = `./imgs/${n}-.jpg`;
      //给图片添加加载完成事件
      img.addEventListener("load", loadHandler);
    }
    function loadHandler(e) {
      //复制img,将每次复制的img放入li中
      //如果直接放入,每次img的url改变,最终只放入最后一张图片
      var img = this.cloneNode(false);
      //给图片添加宽度
      img.style.width = width + "px";
      //求出heightList中最小的一项
      var min = Math.min.apply(null, heightList);
      //得到最小一项额索引值,这个索引值对应liList中的列
      var index = heightList.indexOf(min);
      //将图片放入高度最小的那一列
      liList[index].appendChild(img);
      //将放入图片的高度累加到最小项上,
      //注意先放图片,再计算高度
      heightList[index] += img.height;
      /* 当浏览器出现滚动条时,bodyWidth的值发生改变,
      应该重新计算width,并将每列的宽度和之前放入的图片的宽度也改变 */
      if (bodyWidth !== document.body.clientWidth) resize();
     //图片一共79张,n大于79张跳出,不再加载图片
      n++;
      if (n > 79) return;
      this.src = `./imgs/${n}-.jpg`;
    }

    //当浏览器窗口宽度发生改变,重新设置li和img的宽度
    function resize() {
      //重新获取当前可视窗口的宽度
      bodyWidth = document.body.clientWidth;
      //重新求出每列的宽度
      width = (bodyWidth - GAP * (COL - 1)) / COL;
      //设置每列的宽度和之前放入的图片的宽度
      var lis = Array.from(document.querySelector("ul").children);
      lis.forEach((item, index) => {
        //设置每列的宽度
        item.style.width = width + "px";
        var height = 0;
        //设置之前放入图片的宽度
        for (var i = 0; i < item.children.length; i++) {
          item.children[i].style.width = width + "px";
          //重新计算每列的高度
          height += item.children[i].height;
        }
        //更新heightList中每列的高度
        heightList[index] = height;
      })
    }

  </script>
</body>

</html>

懒加载

分析:每次只加载可视窗口高度*3高的内容。
监听滚动条滚动事件,当滚动条滚动超过可视高度时,继续加载图片。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    body {
      margin: 0;
      padding: 0;
    }

    ul {
      list-style: none;
      margin: 0;
      padding: 0;
    }

    ul::after {
      content: "";
      height: 0;
      clear: both;
      overflow: hidden;
      visibility: hidden;
      display: block;
    }

    li {
      float: left;
    }
  </style>
</head>

<body>
  <ul></ul>

  <script>
    const COL = 5,
      GAP = 10;
    var liList = [], heightList = [], n = 2;
    var width, bodyWidth,imgs;
    init();
    function init() {
      bodyWidth = document.body.clientWidth;
      width = (bodyWidth - GAP * (COL - 1)) / COL;
      var frag = document.createDocumentFragment();
      for (var i = 0; i < COL; i++) {
        var li = document.createElement("li");
        Object.assign(li.style, {
          width: width + "px",
          marginLeft: i === 0 ? "0px" : GAP + "px"
        });
        liList.push(li);
        heightList.push(0);
        frag.appendChild(li);
      }
      document.querySelector("ul").appendChild(frag);
      loadImg();
      window.addEventListener("resize",resize);
      //添加滚动条滚动事件,滚动条滚动时,继续加载后面三屏的内容
      window.addEventListener("scroll",scrollHandler);
    }


    function loadImg() {
      imgs = new Image();
      imgs.src = `./imgs/${n}-.jpg`;
      imgs.addEventListener("load", loadHandler);
    }
    function loadHandler(e) {
      var img = this.cloneNode(false);
      img.style.width = width + "px";
      var min = Math.min.apply(null, heightList);
      var index = heightList.indexOf(min);
      liList[index].appendChild(img);
      heightList[index] += img.height;
      if (bodyWidth !== document.body.clientWidth) resize();
      //懒加载:每次只加载可视窗口高度*3高的内容
      if(document.body.clientHeight-document.documentElement.scrollTop>document.documentElement.clientHeight*3) return;
      //将改变src的代码放到一个新函数reload中,方便懒加载,在滚动条滚动时重新触发
      reload();
    }
    function reload(){
      n++;
      if (n > 79) return;
      // 因为在新的函数中调用,this指向发生改变,可以使用箭头函数改变this指向,也可以将img变量设置成全局变量,方便调用
      //此处我将img变量设置成全局变量
      // this.src = `./imgs/${n}-.jpg`;
      imgs.src = `./imgs/${n}-.jpg`;
    }
    function resize() {
      bodyWidth = document.body.clientWidth;
      width = (bodyWidth - GAP * (COL - 1)) / COL;
      var lis = Array.from(document.querySelector("ul").children);
      lis.forEach((item, index) => {
        item.style.width = width + "px";
        var height = 0;
        for (var i = 0; i < item.children.length; i++) {
          item.children[i].style.width = width + "px";
          height += item.children[i].height;
        }
        heightList[index] = height;
      })
    }
    //滚动条滚动时,继续加载图片
    function scrollHandler(e){
      if(document.body.clientHeight-document.documentElement.scrollTop>document.documentElement.clientHeight*2){
        reload();
      }
    }
  </script>
</body>

</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值