四十一、瀑布流布局(js,jquery,css3三种方式)

一、 简介
1. 实现瀑布流的方法:
JavaScript 原生方法、 jquery 方法、 css3 的多栏布局
二、js 原生方法实现 -- 思想
1. 瀑布流的特点: 等宽不等高
<div id="main">
    <div class="box">
        <div class="pic">
            <img src="images/0.png">
        </div>
    </div>
    <div class="box">
        <div class="pic">
            <img style="height: 200px" src="images/1.png">
        </div>
    </div>
</div>
2. 瀑布流每个图片用 2 div 包裹,一个设置边框的效果, 1 个设置间距, div 之间的间距使用 padding 属性,因为 js 中需获取每列高度,即需知道数据块及之间的距离, JS offsetheight 获取的高度包括 padding 但不包括 margin 在内的高度;
*{margin: 0;padding: 0;}
#main{
    position: relative;
    margin: 0 auto;
}
.box{
    padding: 15px 0 0 15px;
    float: left;
}
.pic{
    border: 1px solid #ccc;
    border-radius: 5px;
    box-shadow: 0 0 5px #cccccc;
    padding: 10px;
}
.pic img{
    width: 165px;
    height: auto;
}
3. 设置列数 ( 页面宽度 / 盒子宽度 ) 及包裹的 div 的宽度 ( 列数 * 盒子宽 ) 和居中属性;
//封装class取元素的方法
function getByClass(parent,clsname){
    var boxarray=new Array(),//用来存储获取到的所有class为box的元素
        elements=parent.getElementsByTagName("*");
    for(var i=0;i<elements.length;i++){
        if(elements[i].className==clsname){
            boxarray.push(elements[i]);
        }
    }
    return boxarray;
}
盒子宽: offsetWidth 获取
页面宽度: document.documentElement.clientWidth 获取
4. 设置盒子瀑布流样式:

获取第一行每个块的高度(offsetHeight),将第5个块放置到第一行块中高度最小的一个下面;

top为高度最小的那个块的高度,left为高度最小的块的left(这里需知道高度最小的块在列数组中的索引);

依次类推,修改每次添加一个块的那个列的高度(原来高度加上增加块的高度)并重新找到高度最小的列,将下一个块补上去;

注意:第一行需不等高,若存在等高需处理等高问题;

function waterfall(parent,cls){
    //将main下所有class的box的元素取出来
    var parents=document.getElementById(parent);
    var boxs=getByClass(parents,cls);
    //计算整个页面显示的列数(页面宽度/box宽)
    var bow_w=boxs[0].offsetWidth;//获取box的宽度
    var cols=Math.floor(document.documentElement.clientWidth/bow_w);//页面宽度clientWidth
    //设置main的宽度并居中显示
    parents.style.cssText='width:'+(cols*bow_w)+'px; margin:0 auto';

    var hArr=[];//用来存储高度的数组
    for(var i=0;i<boxs.length;i++){
        if(i<cols){//第一行
            hArr.push(boxs[i].offsetHeight);
        }else{
            var minH=Math.min.apply(null,hArr);//求数组中高度最低的一列
            var index=minindex(hArr,minH);//获取索引
            //console.log(minH);
            //boxs[i].style.cssText='position:absolute;top:'+minH+'px;left:'+bow_w*index+'px';
            boxs[i].style.position='absolute';
            boxs[i].style.top=minH+'px';
            boxs[i].style.left=bow_w*index+'px';
            //boxs[i].style.left=boxs[index].offsetLeft+'px';
            hArr[index]+=boxs[i].offsetHeight;//修改列的高度
        }
    }
}

//封装求数组最小的索引的函数
function minindex(arr,val) {
    for(var i in arr){
        if(arr[i]==val){
            return i;
        }
    }
}


5.滚动条下滑加载问题

当最后一个块滚动到露出一半高度时加载数据块,即当(块高度/2+块距离

)小于(窗口可视区域的高度+滚动条距离)就加载数据块;

加载数据块,动态创建dom元素,包裹加载数据图片,并调用瀑布流样式函数重新排列样式;

//封装检测是否具备滚动条加载数据块条件
function addbox(){
    var parent=document.getElementById("main");
    var boxs=getByClass(parent,'box');
    var lastBoxH=boxs[boxs.length-1].offsetTop+Math.floor(boxs[boxs.length-1].offsetHeight/2);
    var srcollTop=document.documentElement.scrollTop||document.body.scrollTop;
    var screenheight=document.documentElement.clientHeight||document.body.clientHeight;
    return (lastBoxH<srcollTop+screenheight)?true:false;
}

主代码

window.onload=function(){
    waterfall('main','box');
    //加载json数据
    var dataInt={
        "data":[
            {"src":"7.png"},
            {"src":"1.png"},
            {"src":"11.jpg"}
        ]
    };
    //滚动条加载数据块
    window.onscroll=function(){
        var main=document.getElementById("main");
        if(addbox){
            for(var i=0;i<dataInt.data.length;i++){
                var box=document.createElement("div");
                box.className="box";
                main.appendChild(box);
                var pic=document.createElement("div");
                pic.className="pic";
                box.appendChild(pic);
                var Img=document.createElement("img");
                Img.src="images/"+dataInt.data[i].src;
                pic.appendChild(Img);
            }
            waterfall('main','box');//重新调用瀑布流样式函数排列样式
        }
    }
};

三、jQuery方法实现瀑布流

Jquery优势:链式操作、隐式迭代

1.封装瀑布流排列样式方法

注意:jQuerywidth()方法获取元素的宽,outerWidth()获取元素的宽包含paddingmargin边框等宽度; height()outerHeight()方法同理;

$.inArray(value,array) 获取value这个值在数组array中的索引

each(index,value)遍历中value直接操作是dom元素,需通过$(value)转换为jquery元素进行操作;

function waterfall(){
    //计算列
    var boxs=$("#main>div");
    var w=boxs.eq(0).outerWidth();
    var cols=Math.floor($(window).width()/w);
    //设置main的宽
    $("#mian").width(w*cols).css('margin','0 auto');
    //判断高度最小列 放置后一个数据块
    var harry=[];
    boxs.each(function(index,value){
        var h=boxs.eq(index).outerHeight();//获取每个数据块的高度
        if(index<cols){
            harry[index]=h;
        }else{
            var minH=Math.min.apply(null,harry);
            var minHindex=$.inArray(minH,harry);//获取索引
            $(value).css({  //需要把value的dom对象转换为jQuery $(value)
                'position':'absolute',
                'top':minH+'px',
                'left':minHindex*w+'px'
            });
            harry[minHindex]+=boxs.eq(index).outerHeight(); //改变列的高度
        }
    })
}

2.滚动条加载数据块事件:

遍历json数据对象:$.each(json,function(index,value){});

$(window).on('load',function(){
    waterfall();

    //加载json数据
    var dataInt={
        "data":[
            {"src":"7.png"},
            {"src":"1.png"},
            {"src":"11.jpg"}
        ]
    };

    $(window).on('scroll',function(){
        if(addbox){
            $.each(dataInt.data,function(index,value){ //遍历json数据
                var box=$('<div></div>').addClass('box').appendTo($('#main'));
                var pic=$('<div>').addClass('pic').appendTo($(box));
               //console.log($(value).attr('src')); value转化为jQuery对象
                var oimg=$('<img>').attr('src','images/'+$(value).attr('src')).appendTo($(pic));
            });
            waterfall();
        }
    })
});

封装加载数据块条件的方法:

Js中获取元素距离页面顶部的距离为offsetTop(),jquery中为.offset().top

Js中获取自身高度为offsetHeight(),jquery使用outerHeight();

function addbox(){
    var lastbox=$("#main>div").last();//获取最后一个数据块
    var lastboxdis=lastbox.offset().top+Math.floor(lastbox.outerHeight()/2);//获取块距离+自身高度一半
    var scrolltop=$(window).scrollTop();//获取滚动条高度
    var documentH=$(window).height();//获取页面可视区高度
    return (lastboxdis<scrolltop+documentH)?true:false;
}

一、css3方法实现瀑布流--多栏布局实现

语法:column-count   指定元素应分为的列数

  column-width   指定元素的列的宽度

  column-rule 指定所有列之间的规则(宽度,样式,颜色)

      column-gap 指定列之间的差距

注意:IE10opera支持多列属性

兼容性 -moz-  Firefox; -webkit-  safarichrome;

-o- opera; -ms-  ;

#main{
    column-width: 202px;
    -moz-column-width: 202px;
    -webkit-column-width: 202px;
    /*column-count: 5;
    -moz-column-count: 5;
    -webkit-column-count: 5;*/

    column-rule: 1px dashed silver;
    -moz-column-rule:1px dashed silver;
    -webkit-column-rule: 1px dashed silver;

    column-gap: 10px;
    -moz-column-gap: 10px;
    -webkit-column-gap: 10px;

    width: 1200px;
    margin: 10px auto;

}

猜你喜欢

转载自blog.csdn.net/weixin_40976555/article/details/81059882