瀑布流的3种实现方式

1:js 两列布局实现,思路:左右分为两个容器,根据容器的高度(相对低的那一个)决定下一个元素应该放在哪个容器内,这样视觉就实现了瀑布流的效果,代码如下:

  • 瀑布流容器
<!--瀑布流容器-->
<div id="box"></div>

js代码

//接口获取数据,循环展示
 function forList(list){
             var HTML = "";
         for(var i=0;i<list.length;i++){
            HTML+='<li class="item" data="'+i+'">' ;
            HTML+='<div class="box-item">' ;
            HTML+='<img src="'+list[i].sIMG+'" alt=""><div class="text">'+list[i].sTitle+'</div>';
            HTML+= '</div>';
            HTML+= '</li>';
        }
         
             /**
              * HTML ;拼接后的字符串
              * #box,存放瀑布流的容器
              */
              // 调用瀑布流函数
             warterfall(HTML,'#box')
    }
    //拉取数据
    forList(lists1);
    // 瀑布流函数
    function warterfall(HTML,content) {
       //生成左右两个容器及暂时存放元素的容器(hidebox)
        if($(content+' ul').length<=0){
            $(content).append('<ul class="left"></ul><ul class="right"></ul><ul id="hidebox" style="display: none;"></ul>');
        }
        //数据先放在一个隐藏的容器,
        $("#hidebox").html(HTML);

       //取出元素
       var  items=$("#hidebox li");
       //获取左右两个容器
        var leftbox=$(content+' .left');
        var rightbox=$(content+' .right');
        //设置延迟,保证图片加载完成,避免影响左右容器高度的计算,导致数据放到错误的位置
        setTimeout(function () {
            // 左边容器高度
            var leftDivHeight = leftbox.height();
            // 右边容器高度
            var rightDivHeight =rightbox.height();
            items.each(function (index,item) {
                //瀑布流函数,该函数计算左右容器的总高度,决定把下一个元素放在哪个容器里面
                //获取左右容器高度
                leftDivHeight = leftbox.height();
                rightDivHeight =  rightbox.height();
                //把下一个元素放在高度低的容器里面
                if(leftDivHeight<=rightDivHeight) {
                    leftbox.append(item);
                    return;
                }
                rightbox.append(item);
            })
        },500)
    };

效果如下:


优化瀑布流

2:js position定位,思路:js记录左右两列的所有元素并计算总高度,决定下一个元素的放置位置(注意:元素与元素之间不能用margin,因为这样会影响定位)代码如下:

  • 瀑布流容器
<!--瀑布流容器-->
 <ul id="content" class="force-column  listcom"></ul>

js代码

 function warterfall(parent, box) {
         //瀑布流函数,该函数将图片定位到上一行高度最小图片下方,接数据,更新dom后,重新执行该函数
        //将main下的所有class为box的元素取出来
        var oParent = $('#'+parent);
        var oBoxs =oParent.find('.'+box);
        //计算整个页面显示的列数(页面宽/box的宽);
        var oBoxW = oBoxs.eq(0).width();
        var cols = 2;
        var hArr = [];
        for (var i = 0; i < oBoxs.length; i++) {
            var currentBox=oBoxs.eq(i);
            if (i < cols) {
                // 将前2张图片的宽度记录到hArr数组中(第一行的高度)
                hArr.push(currentBox.height());
            } else {
                //从第二行开始就开始找最小的高度了,决定待插入图片该插入到哪里
                // 找到高度最小的值
                var minH = hArr[0]>hArr[1]?hArr[1]:hArr[0];
                var index = hArr.indexOf(minH);
                // 设置最小高度的图片的style为绝对定位,并设置top和left
                currentBox.css({
                    'position':'absolute',
                    'top': minH ,
                    'left': oBoxW * index
                });
                //高度叠加
                hArr[index] += currentBox.height();
            }
        }
    };
  function forList(list){
        var HTML = "";
        for(var i=0;i<list.length;i++){
            HTML+='<li class="item" data="'+i+'">' ;
            HTML+='<div class="box-item">' ;
            HTML+='<img src="'+list[i].sIMG+'" alt=""><div class="text">'+list[i].sTitle+'</div>';
            HTML+= '</div>';
            HTML+= '</li>';
        }
        $("#content").append(HTML);
        setTimeout(function(){
            warterfall("content", "item");
        },3000)
    }
    forList(lists1);
    $(".btn").on('click',function () {
        forList(lists1)
    })

效果如下:


position

完美实现,但是它每次都需要获取全部元素,再重新定位,很耗性能。

3: css实现

页面布局:

<div class="box">
<!--瀑布流存放的位置-->
    <ul id="content" class="force-column  listcom"></ul>
    <div class="btn">加载更多</div>
</div>

样式设置

 .box{
            width: 100%;
            height: 600px;
            overflow: scroll;
        }
        .box .force-column {
            width: 100%;
            position: relative;
            overflow-x: hidden;
              /*设置元素分几列显示*/
            -moz-column-count: 2;
            -webkit-column-count: 2;
            column-count: 2;
        }
        .box-item{
            width: 200px;
            background: yellowgreen;
        }
        img{
            width: 200px;
            height: auto;
        }

假如数据是接口返回的

<script>
    var lists1 = [
                {
                    "title":"1111",
                    "img":"//sy-1254960240.cos.ap-guangzhou.myqcloud.com/smoba/ingame/images/202007/df7cd494edf5292ca388881fdd4cde852.jpg",
                },
                {
                    "title":"2222",
                    "img":"//shp.qpic.cn/cfwebcap/0/eb2832fbac46ba7182052e7e332230ba/0/?width=330&height=186",
                },
                {
                    "title":"3333",
                    "img":"//sy-1254960240.cos.ap-guangzhou.myqcloud.com/smoba/ingame/images/202007/df7cd494edf5292ca388881fdd4cde852.jpg",
                },
                {
                    "title":"4444",
                    "img":"//shp.qpic.cn/cfwebcap/0/615b9a61170c3213965092ea7cc004a6/0/?width=330&height=186",
                },
                {
                    "title":"5555",
                    "img":"//sy-1254960240.cos.ap-guangzhou.myqcloud.com/smoba/ingame/images/202007/df7cd494edf5292ca388881fdd4cde852.jpg",
                },
                {
                    "title":"6666",
                    "img":"//shp.qpic.cn/cfwebcap/0/448097ae928f6f4015758aced9e72cc7/0/?width=330&height=186",
                },
                {
                    "title":"7777",
                    "img":"//shp.qpic.cn/cfwebcap/0/f463c748a8810add5538a76b51aa6f1a/0/?width=330&height=186",
                },
                {
                    "title":"8888",
                    "img":"//shp.qpic.cn/cfwebcap/0/66585db88507b07fff35e2affa365b37/0/?width=943&height=398",
                },
                {
                    "title":"9999",
                    "img":"//sy-1254960240.cos.ap-guangzhou.myqcloud.com/smoba/ingame/images/202007/df7cd494edf5292ca388881fdd4cde852.jpg",
                 },
            ]
    function forList(list){
        var HTML = "";
        for(var i=0;i<list.length;i++){
            HTML+='<li class="item" data="'+i+'">' ;
            HTML+='<div class="box-item">' ;
            HTML+='<img src="'+list[i].img+'" alt=""><div class="text">'+list[i].title+'</div>';
            HTML+= '</div>';
            HTML+= '</li>';
        }
        $("#content").append(HTML)
            // setTimeout(function(){
            //     warterfall("content", "item");
            // },3000)
    }
    forList(lists1)
    $(".btn").on('click',function () {
        forList(lists1)
    })
</script>
  • 打开页面写,效果如下:


    css实现

效果虽然实现了,但是美中不足的是,他有个问题:数据不是按照1-2-3-4,的顺序来排列的,而是左边是1,3,5,右边是2,4,6。对于需要展示的数据对排序有要求的话(比如排行榜),此种方法不合适;如何来解决这个bug,很简单,就是我们需要对数据进行二次处理,把1,3,5数据放在前面,2,4,6f放在后面,这样就可以了,代码如下:

   //数据处理1,3,5,放前面,2,4,6放后面
    function dataFilter(lists){
        var leftArr=[];
        var rightArr=[];
        $.each(lists,function (index,value) {
           if(index%2==0) {
               leftArr.push(value)
           }else {
               rightArr.push(value)
           }
        })
        var currentArr= [].concat(leftArr,rightArr);
        return currentArr
    }
      forList(dataFilter(lists))

效果如下:


简单数据处理
  • ,此时数据看起来是按照顺序排列的,并且均分放置,也就是两列的列表个数几乎是一样的,但是如果两边的数据因为文字或者图片差异比较大,是否会导致两列高度差异比较大的问题呢?,我们来修改数据看一下,比如增加一些文字,效果如下:


    增加文字

此时看到的结果是:即使两列数据不同,不会导致两列的高度差异很大,因为根据高度差,数据的排列已经发生了改变,比如,第7个列表笨应该放在第一列的最后,现在因为两边高度的问题,而自动放在了第2列的第一位,也就是我们之前的担心是多余的,系统已经做了处理,但是这样的实现方式,还是有我们之前顾虑的问题,就是对数据的排列有要求的需求,这种方法是不适合的。

以上就是我想到的瀑布流的几种实现方式,欢迎大家有更好的方式的话,我们一起交流一下

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

推荐阅读更多精彩内容