瀑布流布局

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

实现的基本思路:

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

实现举例:

<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属性即可。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342

推荐阅读更多精彩内容