美文网首页
原生js实现瀑布流效果

原生js实现瀑布流效果

作者: 前端毛毛 | 来源:发表于2018-10-23 13:44 被阅读0次

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

    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 () {
        // 1. 实现瀑布流布局
        waterFull("main", "box");
    
        // 2. 动态加载图片
        var timer1 = null;
        window.onscroll = function () {
            clearTimeout(timer1);
            timer1 = setTimeout(function () {
                if(checkWillLoadImage()){
                    // 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 = "images/" + dataArr[i].src;
                        newPic.appendChild(newImg);
                    }
    
                    // 2.3 重新布局
                    waterFull("main", "box");
                }
            }, 200);
        };
        // 3. 窗口的大小发生改变
        var timer = null;
        window.onresize = function () {
            clearTimeout(timer);
            // 节流
            timer = setTimeout(function () {
                waterFull('main', 'box');
            }, 200);
        }
    };
    
    /**
     * 实现瀑布流布局
     */
    function waterFull(parent, child) {
        // 1. 父盒子居中
        // 1.1 获取所有的盒子
        var allBox = $(parent).getElementsByClassName(child);
        // 1.2 获取子盒子的宽度
        var boxWidth = allBox[0].offsetWidth;
        // 1.3 获取屏幕的宽度
        var screenW = document.documentElement.clientWidth;
        // 1.4 求出列数
        var cols = parseInt(screenW / boxWidth);
        // 1.5 父盒子居中
        $(parent).style.width = cols * boxWidth + 'px';
        $(parent).style.margin = "0 auto";
    
    
        // 2. 子盒子的定位
        // 2.1 定义高度数组
        var heightArr = [], boxHeight = 0, minBoxHeight = 0, minBoxIndex = 0;
        // 2.2 遍历子盒子
        for (var i = 0; i < allBox.length; i++) {
            // 2.2.1 求出每一个子盒子的高度
            boxHeight = allBox[i].offsetHeight;
            // 2.2.2 取出第一行盒子的高度放入高度数组
            if (i < cols) { // 第一行
                heightArr.push(boxHeight);
                allBox[i].style = '';
            } else { // 剩余行
                // 1. 取出最矮的盒子高度
                minBoxHeight=Math.min.apply(this,heightArr);
                // 2. 求出最矮盒子对应的索引
                minBoxIndex = getMinBoxIndex(heightArr, minBoxHeight);
                // 3. 子盒子定位
                allBox[i].style.position = "absolute";
                allBox[i].style.left = minBoxIndex * boxWidth + 'px';
                allBox[i].style.top = minBoxHeight + 'px';
                // 4. 更新数组中的高度
                heightArr[minBoxIndex] += boxHeight;
            }
        }
    
        // console.log(heightArr, minBoxHeight, minBoxIndex);
    }
    /**
     * 获取数组中最矮盒子高度的索引
     * @param arr
     * @param val
     * @returns {number}
     */
    function getMinBoxIndex(arr, val) {
        for(var i=0; i<arr.length; i++){
            if(arr[i] === val){
                return i;
            }
        }
    }
    function $(id) {
        return typeof id === "string" ? document.getElementById(id) : null;
    }
    /**
     * 判断是否具备加载图片的条件
     */
    function checkWillLoadImage() {
        // 1. 获取最后一个盒子
        var allBox = document.getElementsByClassName("box");
        var lastBox = allBox[allBox.length - 1];
    
        // 2. 求出最后一个盒子自身高度的一半 + offsetTop
        var lastBoxDis = lastBox.offsetHeight * 0.5 + lastBox.offsetTop;
    
        // 3. 求出屏幕的高度
        var screenW = document.body.clientHeight || document.documentElement.clientHeight;
    
        // 4. 求出页面偏离浏览器的高度
        var scrollTop = scroll().top;
    
        return lastBoxDis <= screenW + scrollTop;
    }
    
    
    

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

    相关文章

      网友评论

          本文标题:原生js实现瀑布流效果

          本文链接:https://www.haomeiwen.com/subject/axemzftx.html