一、图片的预加载

图片的预加载就是在加载 js 的时候,提前加载图片,加载完成之后(图片会存到浏览器缓存中),再将图片路径赋值给页面的图片。
图片预加载的实现原理:
1、先不给页面图片的src属性赋值
2、将图片的路径放在一个数组中;
3、创建一个image对象;
4、将该image对象的src属性设为即将要加载的图片的路径;
5、给该image对象设置加载完成事件,加载完成之后(图片会存到浏览器缓存中),再将该image对象的src属性值赋值给页面的图片。

举例:

<img src="" id="img" alt="加载失败!"/>
<script>
    //使用远程路径加载图片,将图片的远程路径放在数组中
    var str = 
    ["https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1298282578,487436402&fm=26&gp=0.jpg", 
    "https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=1259401293,3815682953&fm=26&gp=0.jpg"
    ];
    var imgdata=document.querySelector("#img");
    //创建一个image对象
    var image=new Image();
    image.src=str[0];
    //图片加载完成事件 加载完成之后 将路径赋值给页面的图片
    image.onload=function(){
        imgdata.src=this.src;
    }
</script>

二、图片的懒加载

当一个页面需要加载的图片过多时,为了缓解服务器压力,增强用户体验,可以使用图片的懒加载,即:优先加载可视区域的内容,其他部分等进入了可视区域再加载。
图片懒加载的实现原理:
1、设置图片src属性为同一张图片,或者先不给src属性赋值,同时自定义一个data-img(可以自定义属性名称)属性来存储图片的真实地址;
2、 判断图片是否在可视区域;
3、 当图片出现在可视区域时,再将data-img的值赋给该区域图片的src属性。

代码如下:

<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .box {
            height: 1000px;
        }

        .imgbox {
            width: 820px;
            border-top: 1px solid #000000;
            margin: 0 auto;
        }

        .imgbox > img {
            width: 190px;
            margin: 5px;
        }
    </style>
</head>
<body>
<div class="box">

</div>
<div class="imgbox">
    <img data-img="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1578121069,3381500888&fm=15&gp=0.jpg"
         src="./image/baseimg.png" alt=""/>
    <img data-img="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1578121069,3381500888&fm=15&gp=0.jpg"
         src="./image/baseimg.png" alt=""/>
    <img data-img="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1578121069,3381500888&fm=15&gp=0.jpg"
         src="./image/baseimg.png" alt=""/>
    <img data-img="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1578121069,3381500888&fm=15&gp=0.jpg"
         src="./image/baseimg.png" alt=""/>
    <img data-img="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1578121069,3381500888&fm=15&gp=0.jpg"
         src="./image/baseimg.png" alt=""/>
    <img data-img="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1578121069,3381500888&fm=15&gp=0.jpg"
         src="./image/baseimg.png" alt=""/>
    <img data-img="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1578121069,3381500888&fm=15&gp=0.jpg"
         src="./image/baseimg.png" alt=""/>
    <img data-img="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1578121069,3381500888&fm=15&gp=0.jpg"
         src="./image/baseimg.png" alt=""/>
</div>
<script>
    var imgbox = document.querySelector(".imgbox");
    window.onscroll = function () {
        if (checkbool()) {
            setTimeout(function () {
                for (var i = 0; i < imgbox.children.length; i++) {
                    imgbox.children[i].src = imgbox.children[i].getAttribute("data-img");
                }
            }, 1000);
        }
    };
    function checkbool() {
        return imgbox.offsetTop - window.scrollY <= document.documentElement.clientHeight;
    }
</script>
</body>

三、图片瀑布流加载的案例

      瀑布流,又称瀑布流式布局。是比较流行的一种网站页面布局,视觉表现为参差不齐的多栏布局,随着页面滚动条向下滚动,这种布局还会不断加载数据块并附加至当前尾部。

创建图片时需要一个一个创建,否则无法动态获取元素的左边距和上边距;
先加载第一页的图片,滚动轴滑到底部,再加载第二批、第三批、、、

案例一:

使用图片的预加载,再将一次性计时器使用递归做成循环计时器,实现每张图片的延迟加载。(具体代码如下)

<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .box{
            position: relative;
            width: 1100px;
            min-height: 200px;
            border: 1px solid #000000;
            margin: 0 auto;
        }
        .list{
            position: absolute;
            width: 100px;
            height: auto;
            margin: 5px;
            opacity: 0;
            transition: opacity .2s linear;
        }
    </style>
</head>
<body>
<div class="box">
</div>
<script>
    //加载图片的远程路径
    var str = [
        "https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1298282578,487436402&fm=26&gp=0.jpg",
        "https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=1259401293,3815682953&fm=26&gp=0.jpg",
        "https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=2784122952,3562453652&fm=15&gp=0.jpg",
        "https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=2553781316,2986187814&fm=26&gp=0.jpg",
        "https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1578121069,3381500888&fm=15&gp=0.jpg"
    ];
    var box = document.querySelector(".box");
    var list = document.getElementsByClassName("list");
    var srcIndex = 0;//获取图片路径随机值
    var imgCount = 40;//默认加载图片的数量
    var count = 0;
    var showrow = 10;
    var maxHeight = 0;
    creatimage();
    function creatimage() {
        //新建一个Image对象
        var beforeimg = new Image();
        beforeimg.classList.add("list");
        //设置图片索引随机值
        srcIndex = parseInt(Math.random() * str.length);
        beforeimg.src = str[srcIndex];
        //图片预加载
        beforeimg.onload = function () {
            var that = this;
            box.appendChild(this);
            //这里实现延迟加载 使用一次性计时器 递归来实现
            setTimeout(function () {
                setimagestyle(that);
                if (count >= imgCount - 1) {
                    return;
                }
                count++;
                creatimage();
            }, 100);
        };
        beforeimg.onerror = function () {
            beforeimg.alt = "图片加载失败";
        };
        beforeimg = null;
    }
    //设置Image对象的相关样式
    function setimagestyle(obj) {
        obj.style.opacity = 1;
        //图片的左偏移
        obj.style.left = (count % showrow * 110) + "px";

        var top = 0;
        if (count < showrow) {
            top = 0;
        }
        else {
            //上一行同一位置的元素的offsetHeight 加上上一行同一位置的元素上边框到box上边框的距离
            top = list[count - showrow].offsetHeight + list[count - showrow].offsetTop;
        }
        obj.style.top = top + "px";
        //动态计算box最大高
        var offset = obj.offsetHeight + top;
        //var offset=obj.offsetHeight+top
        if (offset >= maxHeight) {
            maxHeight = offset;
        }
        box.style.height = maxHeight + 10 + 20 + "px";   //20是让box多20px的高
    }

    //滚动条事件
    window.onscroll = function () {
        //console.log(this.scrollY);   //12.8
        //console.log(document.documentElement.clientHeight);   //714
        //console.log(document.body.clientHeight);  //739

        var htmlH = document.documentElement.clientHeight;
        var bodyH = document.body.clientHeight;
        if (this.scrollY + htmlH >= bodyH) {
            imgCount += 20;
            count++;
            creatimage();
        }
    };
</script>
</body>

案例二:

使用的本地图片,所以没有使用预加载

<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        #box {
            position: relative;
            width: auto;
        }

        .list {
            position: absolute;
            width: 120px;
            border: 4px solid #c0c0c0;
            box-sizing: border-box;
        }

        .list > img {
            width: 100%;
            height: auto;
            vertical-align: middle;
        }
    </style>
</head>
<body>
<div id="box">

</div>
<script>
    //将图片名称存在数组里边
    var defaul = 40;  //定义默认显示值
    var count = 0;  //记录一行显示几个
    var sleft = 0;   //当前屏幕留下的空白值平分给每个元素的值
    var boxh = 0;  //记录box的高
    var arr = ["3.jpg", "4.jpg", "5.jpg", "7.jpg", "12.jpg", "14.jpg", "17.jpg", "19.jpg", "20.jpg"];
    var box = document.getElementById("box");
    //动态获取创建的div
    var list = document.getElementsByClassName("list");

    //构建一个算法 计算count
    proNum();
    function proNum() {
        count = Math.floor(this.innerWidth / 120);
        sleft = (this.innerWidth - count * 120 - 25) / count;
    }

    /*
     * 构建方法 创建元素添加到box里边
     * */
    for (var i = 0; i < defaul; i++) {
        creatElement();
    }
    function creatElement() {
        //创建div包img元素
        var imgbox = document.createElement("div");
        imgbox.className = "list";
        //创建img元素
        var img = new Image();
        img.src = "./img/" + arr[Math.floor(Math.random() * 9)];
        imgbox.appendChild(img);
        box.appendChild(imgbox);
    }

    /*
     * 添加一个加载完成事件
     * */
    window.onload = function () {
        //设置list的left top 以及box的高   要注意offset值不对的问题,需要在浏览器加载完成后再获取
        setOffset();
        function setOffset() {
            //for循环遍历list    设置每个list的left 和top
            for (var i = 0; i < list.length; i++) {
                //top值
                if (i < count) {
                    list[i].style.top = "5px";
                }
                else {
                    list[i].style.top = (list[i - count].offsetHeight + list[i - count].offsetTop + 5) + "px";
                }
                //left值
                list[i].style.left = (i % count) * (sleft + 120) + "px";
                //box 的高
                if (list[i].offsetHeight + list[i].offsetTop >= boxh) {
                    boxh = list[i].offsetHeight + list[i].offsetTop + 10;
                }
                box.style.height = boxh + "px";
            }
        }

        /*
         * 添加浏览器的滚动条事件
         * */
        this.onscroll = function () {
            if (this.scrollY + this.innerHeight >= document.documentElement.scrollHeight) {
                defaul += count;  //每次在原基础上多一行
                for (var i = defaul - count; i < defaul; i++) {
                    creatElement();
                }
                setOffset();
            }
        };

        /*
         * 浏览器窗口发生变化事件
         * */
        var time = null;
        this.onresize = function () {
            if(time)clearTimeout(time);
            time = setTimeout(function () {
                //浏览器窗口发生变化后,重新计算count、sleft、box高、list的left和top
                proNum();
                boxh=0;
                setOffset();
            },300)
        }
    }


</script>
</body>