js懒加载&瀑布流

什么是瀑布流

瀑布流又称瀑布流式布局,是比较流行的一种网站页面布局方式。视觉表现为参差不齐的多栏布局,最早采用此布局的是网站是 Pinterest,后逐渐在国内流行。

链接文章:浅谈瀑布流

什么是懒加载

懒加载其实就是延迟加载,是一种对网页性能优化的方式。

比如当访问一个页面的时候,优先显示可视区域的图片,而不一次性加载所有图片,当需要显示的时候再发送图片请求,避免打开网页时加载过多资源。

什么时候用懒加载

当页面中需要一次性载入很多图片的时候,往往都是需要用懒加载的。

懒加载原理

链接文章:js实现图片懒加载原理

<img>标签有一个属性是src,用来表示图像的URL,当这个属性的值不为空时,浏览器就会根据这个值发送请求;如果没有src属性,就不会发送请求。

那可不可以这样想,图片一开始不设置src,当需要的时候再设置?
可以。
我们先不给< img >设置src,把图片真正的URL放在另一个属性data-src中,在需要的时候也就是图片进入可视区域的之前,将URL取出放到src中。

涉及的知识点:
(1) 图片距离顶部的高度:img.offsetTop
(2) 当前窗口的高度:window.innerHeight
(3) 滚动条滚动的高度:document.body.scrollTop || document.documentElement.scrollTop

加载图片的判断条件:
图片距离顶部的距离 < 浏览器滚动条滚动的高度 + 浏览器窗口的高度
在这里插入图片描述

图片懒加载、瀑布流效果 示例

案例1:div模拟图片加载

为了更直观看到效果,没有放入真正的图片,而是用div去模拟图片;创建div,然后设置随机高度模拟不同图片的高度。

(注意:以下说的图片皆是div模拟的图片,以背景形式展示图片)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="./js/jquery-3.2.1.js"></script>
    <style>
        div {
            position: absolute;
            width: 200px;
            color: white;
        }
    </style>
</head>
<body>
    <script>
        class WaterFall{
            constructor() {
                
            }
            //生成div,每次执行这个函数都生成20个div,用来模拟图片
            // 每次生成20张div
            createDiv(){
                for(let i=0; i<20; i++){
                    let div = document.createElement("div");
                    div.innerHTML = i;
                    let rnd = Math.round(Math.random()*300+50);//生成50~350的随机数
                    div.style.height = rnd + "px";
                    div.date_src = "url(./img/" + i + ".jpg)";
                    div.style.backgroundSize = "200px" + " " + rnd + "px";
                    document.body.appendChild(div);
                }
                this.change();
            }
            
            change(){
                let oArrDiv = document.getElementsByTagName("div");//获取所有的div
                //计算的是窗口显示大小变化时,显示的几个div(每个div宽度200px,间隔10px),所以,n代表的是一行最多排几个div
                let n = Math.floor(window.innerWidth/210);//innerwidth 返回窗口的文档显示区的宽度。  
                let arrH = [];//记录之前对应每列div的高度和
               
                //遍历所有div,根据窗口大小安排一行几个div;
                //因为图片高度随机,所以第一次把div模拟的图片放上去后,计算每一列的总高度;
                //在最短的列下面添加新的div,位移left值以该列index计算,top值以每列高度加上垂直间距10来计算。
                for(let i=0; i<oArrDiv.length; i++){
                    //图片距离顶部的距离 < 浏览器滚动条滚动的高度 + 浏览器窗口的高度
                    if(oArrDiv[i].offsetTop < document.documentElement.scrollTop + document.documentElement.clientHeight){
                        this.loadImg(oArrDiv[i]);//加载图片
                    }    
    
                    //除了第一行上传图片的top为0外,其余图片都需要进行判断,在最小高度列下面添加新的图片,top=该列此时高度+垂直间距10px。    
                    //在首行排列完后,arrH[i]就已经代表每列的总高度,而arrH.length则代表窗口最大容纳div数。
                    //如果arrH.length==当前窗口水平容纳的最大div数,说明不是第一行。
                    if(arrH.length == n){             	
                        let index = this.findMin(arrH);//寻找最小高度的一列,然后返回这一列的序列号
                        oArrDiv[i].style.left = 200*index + 10*index + "px";//然后计算这列水平方向的距离
                        oArrDiv[i].style.top = arrH[index] + 10 + "px";//然后计算这列垂直方向的距离。在前面对应每列div的高度总和的基础上,把新的垂直间距也加上。
                        arrH[index] += oArrDiv[i].offsetHeight + 10;//然后,更新该列的总高度,把这一列新添加的元素的高度也加上
                    }else{
                        //第一行
                        oArrDiv[i].style.top = "0" + "px";
                        oArrDiv[i].style.left = 200*i + 10*i + "px";//因为每个div的宽度都是200px,所以此处将每个div距离为10px(div绝对定位)
                        arrH[i] = oArrDiv[i].offsetHeight;//offsetHeight只读属性,返回该元素的像素高度。
                        //所以,此时arrH[i]记录图片初始高度
                    }
                }
            }
            //找到最小高度列
            findMin(arrH){
                let index = 0;
                for(let i=0; i<arrH.length; i++){
                    if(arrH[index]>arrH[i]){
                        index = i;
                    }
                }
                return index;
            }
            
            // 滚动条如果超过400,则自动加载,重新创建新的div出来
            moveScroll(){
                let top = 0;//用来记录垂直方向滚动的值
                let that = this;
                window.onscroll = function(){
                    top = document.body.scrollTop || document.documentElement.scrollTop;
                    // console.log("top:",top);
                    if(top > 400){
                        that.createDiv();
                        // console.log("top>400")
                        // console.log("网页被卷去的高:",document.body.scrollTop)
                        // console.log("要获取当前页面的滚动条纵坐标位置,用:",document.documentElement.scrollTop)
                    }
                }
            }
            
            loadImg(oDiv){
                //如果此div的属性不存在,说明未被加载
                if(oDiv.src == null){
                    oDiv.style.backgroundImage = oDiv.date_src;
                }
            }
        }
        
        let wf = new WaterFall();
        wf.createDiv();
        // wf.createDiv();
        wf.moveScroll();


        // console.log("浏览器窗口的内部高度:",window.innerHeight)
        // console.log("表示HTML文档所在窗口的当前高度:",document.documentElement.clientHeight)
        // console.log("Document对象的body属性对应HTML文档的<body>标签:",document.body.clientHeight)
        // console.log("网页被卷去的高:",document.body.scrollTop)
        // console.log("要获取当前页面的滚动条纵坐标位置,用:",document.documentElement.scrollTop)
    </script>
</body>
</html>

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值