1. 程式人生 > >四十一、瀑布流佈局(js,jquery,css3三種方式)

四十一、瀑布流佈局(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;

}