原生js实现瀑布流效果 函数封装

实现目标:实现瀑布流布局、当滚动条滚动到一定距离时加载图片
瀑布流布局:结合窗口改变 定位第一行的盒子 第二行第一个盒子接到第一行最矮的盒子下面 当接完后更新最矮盒子 以此类推
滚动加载图片:案例是用数组对象实现图片加载 条件是当加载到最后一张图片一半+最后盒子的offsetTop小于等于屏幕的高度+滚动的距离时 加载图片

html+css

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>瀑布流</title>
    <style>
        body, h1, h2, h3, h4, h5, h6, hr, p, blockquote, dl, dt, dd, ul, ol, li, pre, form, fieldset, legend,
        button, input, textarea, th, td { margin:0; padding:0;border:none;list-style:none; }
        body,html{
            width: 100%;
            height: 100%;
        }
        #main{
            position: relative;
        }
        .box{
            float: left;
            padding: 15px 0 0 15px;

        }
        .pic{
            border:1px solid #ccc;
            border-radius: 5px;
            padding: 10px;
        }
        .pic img{
            width: 150px;
        }
    </style>

</head>
<body>
<div id="main">
    <div class="box">
        <div class="pic"><img src="imgs/img01.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img02.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img03.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img04.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img05.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img06.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img07.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img08.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img09.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img10.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img11.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img12.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img13.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img14.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img15.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img16.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img17.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img18.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img19.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img20.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img21.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img22.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img23.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img24.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img25.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img26.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img27.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img28.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img29.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img30.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img31.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img32.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img33.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img34.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img35.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img36.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img37.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img38.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img39.jpg" alt=""></div>
    </div>
    <div class="box">
        <div class="pic"><img src="imgs/img40.jpg" alt=""></div>
    </div>
</div>
<script src="js/index.js"></script>
<script src="js/scroll.js"></script>
</body>
</html>

注意:index.js为主要js代码 scroll.js为封装scroll的代码 链接:https://www.jianshu.com/p/6427731bb125
css方面:添加定位

window.onload=function () {
    //调用函数 父盒子居中
    waterFull('main','box');
    //动态加载图片
    window.onscroll=function () {
        if(checkWillLoadImg()){
            // 2.1 造数据
            var dataArr = [
                {"src": "img04.jpg"},
                {"src": "img06.jpg"},
                {"src": "img08.jpg"},
                {"src": "img09.jpg"},
                {"src": "img10.jpg"},
                {"src": "img12.jpg"},
                {"src": "img14.jpg"},
                {"src": "img16.jpg"},
                {"src": "img18.jpg"}
            ];

            // 2.2 创建元素
            for(var i=0;i<dataArr.length;i++){
                var newBox=document.createElement('div');
                newBox.className="box";
                $('main').appendChild(newBox);

                var newPic=document.createElement('div');
                newPic.className="pic";
                newBox.appendChild(newPic);

                var newImg=document.createElement('img');
                newImg.src="imgs/"+dataArr[i].src;
                newPic.appendChild(newImg);
            }

            //从新布局
            waterFull('main','box');
        }
    }

    //瀑布流布局函数封装
    function waterFull(parent,child) {
        //1.获取所有盒子
        var allBox=$(parent).getElementsByClassName(child);
        //获取盒子宽度
        var boxWidth=allBox[0].offsetWidth;
        //获取窗口宽度
        var screenW=document.documentElement.clientWidth;
        //获取列数  综合窗口改变
        var cols=parseInt(screenW/boxWidth);
        //父盒子居中 将列数乘以每个盒子的宽度
        $(parent).style.width=cols*boxWidth+"px";
        $(parent).style.margin="0 auto";

        //2.子盒子定位
        //获取所有盒子的高度 将第一行的高度加入数组
        var heightArr=[],boxHeight,minBoxHeight,minBoxIndex;
        for(var i=0;i<allBox.length;i++){
            boxHeight=allBox[i].offsetHeight;
            //判断条件  列数决定第一行和第二行
            if(i<cols){
                //第一行
                heightArr.push(boxHeight);
            }
            else{
                //剩余行 取出第一行最小值
                minBoxHeight=Math.min.apply(this,heightArr);
                //原理:求出最小高度的索引*boxWidth即为第二行第一个的left
                minBoxIndex=MinBoxIndex(heightArr,minBoxHeight);
                allBox[i].style.position="absolute";
                allBox[i].style.left=minBoxIndex*boxWidth+"px";
                allBox[i].style.top=minBoxHeight+"px";

                //最重要的一步 更新heightArr里的最小值
                heightArr[minBoxIndex]+=boxHeight;
            }
        }
    }
    //封装获取元素
    function $(id) {
        return typeof id === "string" ? document.getElementById(id) : 0;
    }
    //求数组中最小值的索引 arr为数组 min为最小值
    function MinBoxIndex(arr,min) {
        for(var i=0;i<arr.length;i++){
            if(arr[i]==min){
                return i;
            }
        }
    }
    //判断是否符合加载图片的条件 返回true 或 false
    function checkWillLoadImg() {
        //获取所有盒子
        var allBox=document.querySelectorAll('.box');
        //获取最后一个盒子
        var lastBox=allBox[allBox.length-1];
        //获取最后一个盒子一榜的高度和offsetTop
        var lastBoxList=lastBox.offsetHeight*0.5+lastBox.offsetTop;
        //获取屏幕高度 兼容处理
        var screenH=document.body.clientHeight || document.documentElement.clientHeight;
        //判断
       return lastBoxList <= screenH+scroll().top;
    }

}

步骤:瀑布流布局封装
传入参数父盒子 子盒子
1.获取所有盒子
2.获取盒子宽度 窗口宽度
3.结合窗口改变 获取列数
4.子盒子定位
5.获取第一行盒子的宽度加入数组 (遍历所有的子盒 子 i小于列数即为第一行 )
6.取出第一行最小值 Math.min.apply(this,数组)
7.添加剩余行的定位 left=最小值的索引*盒子的宽度 top=最小盒子的高度(最小值的索引函数封装实现)

猜你喜欢

转载自blog.csdn.net/wyq12138/article/details/83305702