瀑布流布局

作者: DeeJay_Y | 来源:发表于2017-08-28 16:08 被阅读3次

    瀑布流:每个内容的宽度相等,高度是随机的
    布局的基本原则,第一排排满之后,下面的元素将放到高度最短的那一列下面

    实现的基本思路:

    • 需要创建一个数组,这个数组存储的每一项都为对应列的高度,而下标就为当前的列
    • 需要得到每个元素的宽度

    实现举例:

    <style>
            .content {
                position: relative;
            }
            .item {
                /*绝对定位,并且每个元素的宽度是一定的*/
                position: absolute;
                width: 200px;
                margin-right: 10px;
                margin-top:  10px;
                transition: all 1s;
            }
            .h1 {
                height: 200px;
                background: #f4b300;
            }
            .h2 {
                height: 300px;
                background: #691bbb;
            }
            .h3 {
                height: 400px;
                background: #006ac1;
            }
        </style>
    </head>
    <body>
         <div class="content">
             <div class="item h1">1</div>
             <div class="item h3">2</div>
             <div class="item h2">3</div>
             <div class="item h2">4</div>
             <div class="item h3">5</div>
             <div class="item h1">6</div>
             <div class="item h2">7</div>
             <div class="item h3">8</div>
             <div class="item h1">9</div>
             <div class="item h2">10</div>
             <div class="item h3">11</div>
             <div class="item h3">12</div>
             <div class="item h2">13</div>
             <div class="item h1">14</div>
         </div>
    

    结构和样式如上,h1,h2,h3用来模拟随机的高度。
    JS部分如下:

         <script src="../jquery-3.2.1.min.js"></script>
         <script>
    //         创建数组
             var itemArr = [];
             //得到数组一共有多少项,即要排列的元素到底有几列,可以通过content的宽度除以item的宽度,然后进行取整就能得到总共有多少列
             var itemColumn = parseInt($('.content').width() / $('.item').width());
    //         console.log(itemColumn)
             //进行数组的初始化,有itemColumn项,每项都先设为0,表示当前没有元素,高度为0
             for (var i = 0; i < itemColumn; i ++) {
                itemArr[i] = 0;
             }
             //数组初始化完毕,然后涉及到需要得到数组中值最小的一项,以及要得到最小的这一项的下标,可以使用Math.min和indexOf()两个方法
             //进行遍历所有的item,将每个item放到当前高度最短的那一列的下边
             $('.item').each(function () {
                 var minHeight = Math.min.apply(null,itemArr);//数组中值最小的一项,即高度最短的那一列的高度值
                 var minIndex = itemArr.indexOf(minHeight); // 对应列的下标
                 $(this).css({
                     left: minIndex * $('.item').outerWidth(true), //这个outerWidth,有true代表包括margin,不写true代表只包括border
                     top: minHeight,
                 })
                 itemArr[minIndex] += $(this).outerHeight(true); //放置完当前遍历元素时,将相应的高度加到当前列的高度上
    //             console.log('h',minHeight)
    //             console.log('i',minIndex);
             })
         </script>
    

    代码的整体思路已经很清晰了,但是有地方需要注意:

    • 涉及到需要得到数组中值最小的一项,以及要得到最小的这一项的下标,可以使用Math.min和indexOf()两个方法。使用Math.min要结合apply()
    • $('.item').outerWidth(true)

    然后基本效果就达到了,但是需要监听窗口大小改变的事件,如果窗口大小改变,重新排列一下。所以我们封装一下我们得到的代码。加上监听事件

             waterFall(); //页面初始化时先执行一次出现布局
             $(window).on('resize',function () { // 监听浏览器窗口大小改变的事件
                 waterFall();
             })
            
             
            function waterFall() {
                //         创建数组
                var itemArr = [];
                //得到数组一共有多少项,即要排列的元素到底有几列,可以通过content的宽度除以item的宽度,然后进行取整就能得到总共有多少列
                var itemColumn = parseInt($('.content').width() / $('.item').width());
    //         console.log(itemColumn)
                //进行数组的初始化,有itemColumn项,每项都先设为0,表示当前没有元素,高度为0
                for (var i = 0; i < itemColumn; i ++) {
                    itemArr[i] = 0;
                }
                //数组初始化完毕,然后涉及到需要得到数组中值最小的一项,以及要得到最小的这一项的下标,可以使用Math.min和indexOf()两个方法
                //进行遍历所有的item,将每个item放到当前高度最短的那一列的下边
                $('.item').each(function () {
                    var minHeight = Math.min.apply(null,itemArr);//数组中值最小的一项,即高度最短的那一列的高度值
                    var minIndex = itemArr.indexOf(minHeight); // 对应列的下标
                    $(this).css({
                        left: minIndex * $('.item').outerWidth(true), //这个outerWidth,有true代表包括margin,不写true代表只包括border
                        top: minHeight,
                    })
                    itemArr[minIndex] += $(this).outerHeight(true); //放置完当前遍历元素时,将相应的高度加到当前列的高度上
    //             console.log('h',minHeight)
    //             console.log('i',minIndex);
                })
            }
    

    此时窗口大小改变时也会相应的重新布局了。还可以进一步封装代码,创建一个对象,把要执行的代码return出来,函数体放到对象内部的属性中。

             var begin = {
                 run: run,
             };
             begin.run();
             function run () {
                 function waterFall() {
                     //         创建数组
                     var itemArr = [];
                     //得到数组一共有多少项,即要排列的元素到底有几列,可以通过content的宽度除以item的宽度,然后进行取整就能得到总共有多少列
                     var itemColumn = parseInt($('.content').width() / $('.item').width());
    //         console.log(itemColumn)
                     //进行数组的初始化,有itemColumn项,每项都先设为0,表示当前没有元素,高度为0
                     for (var i = 0; i < itemColumn; i ++) {
                         itemArr[i] = 0;
                     }
                     //数组初始化完毕,然后涉及到需要得到数组中值最小的一项,以及要得到最小的这一项的下标,可以使用Math.min和indexOf()两个方法
                     //进行遍历所有的item,将每个item放到当前高度最短的那一列的下边
                     $('.item').each(function () {
                         var minHeight = Math.min.apply(null,itemArr);//数组中值最小的一项,即高度最短的那一列的高度值
                         var minIndex = itemArr.indexOf(minHeight); // 对应列的下标
                         $(this).css({
                             left: minIndex * $('.item').outerWidth(true), //这个outerWidth,有true代表包括margin,不写true代表只包括border
                             top: minHeight,
                         })
                         itemArr[minIndex] += $(this).outerHeight(true); //放置完当前遍历元素时,将相应的高度加到当前列的高度上
    //             console.log('h',minHeight)
    //             console.log('i',minIndex);
                     })
                 }
                return (function () {
                    waterFall(); //页面初始化时先执行一次出现布局
                    $(window).on('resize',function () { // 监听浏览器窗口大小改变的事件
                        waterFall();
                    })
                })();
             }
    

    封装代码如上所示,把函数体放到run()中,作为值传递给begin对象的run属性,return的是包含我们想要执行的代码的立即执行函数,这样我们想要开始的时候,只需要调用begin对象的run属性即可。

    相关文章

      网友评论

        本文标题:瀑布流布局

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