瀑布流,木桶,等高,圣杯,雙飛翼布局

1.瀑布流布局

  • 思路:
    要求:當圖片寬度相同,高度不同時;如何做一面圖片墻;每次圖片加載到每列最低的位置;
    1.圖片的容器要相對定位,圖片要相對容器絕對定位;
    2.首先要求出當瀏覽器打開時或者改變大小時,瀏覽器的窗口能放入幾張圖片;即形成幾列;
    3.創建一個空數組來存放每列的高度值;
    4.當有圖片加載時根據數組里存放的高度大小;把圖片放入高度最小的列;
    5.當放入后更改放入后的高度;這樣每次都可以把圖片放入高度最低的列里形成好看的圖片墻了。

  • 重點:

 .content{
            position:relative;
        }
 .item{
            position: absolute;
           transition:all 1s; /*漸變效果*/
         }
 function waterFull(){
                var nodeWidth =$('.item').width();//元素寬度
                var num  =parseInt($('.content').width()/nodeWidth)//一排放多少個(取整)
                var itemArr = [];//存放每列的高度;
                for(var i=0; i<num;i++){//初始化
                itemArr[i]=0;//目前每列高度為0;
            }
            
            $('.item').each(function(){//循環所有圖片
                var minValue = Math.min.apply(null,itemArr) //獲取數組最小值(第一次就是數組的第一項0;)
                var minIndex = itemArr.indexOf(minValue)//獲取最小值的下標;

                $(this).css({//通過改變top left ;放入圖片的位置;
                    top:itemArr[minIndex],
                    left:$(this).outerWidth(true)*minIndex

                })
                itemArr[minIndex] += $(this).outerHeight(true);//更改添加后列的高度
            })

     }  
  • 看下效果:
20170404_183059.gif
  • 優化:

1.在改變窗口大小時重新加載圖片位置
2.當滾動時繼續的加載圖片;(寫一個判斷是否加載的函數checkScroll)
3.當滾動時發送ajax性后端要數據加載圖片;(我這里是自己給的數據json模擬)
4.優化代碼放入立即執行函數;

var WaterFull=(function(){
      function init(){
             waterFull()
            $(window).resize(function(){//改變窗口大小
              waterFull()
           })
            $(window).on('scroll',Scroll)//當窗口滾動時Mocks數據;
           

         }
    function waterFull(){
                var nodeWidth =$('.item').width();//元素寬度
                var num  =parseInt($('.content').width()/nodeWidth)//一排放多少個(取整)
                var itemArr = [];//存放每列的高度;
                for(var i=0; i<num;i++){//初始化
                itemArr[i]=0;//目前每列高度為0;
            }
            
            $('.item').each(function(){//循環所有圖片
                var minValue = Math.min.apply(null,itemArr) //獲取數組最小值(第一次就是數組的第一項0;)
                var minIndex = itemArr.indexOf(minValue)//獲取最小值的下標;

                $(this).css({//通過改變top left ;放入圖片的位置;
                    top:itemArr[minIndex],
                    left:$(this).outerWidth(true)*minIndex

                })
                itemArr[minIndex] += $(this).outerHeight(true);//更改添加后列的高度
            })

     }  
     function Scroll(){
          var dataInt = {
            'data':[{'src':'1.png'},{'src':'2.png'},{'src':'3.png'},{'src':'4.png'},{'src':'5.png'},{'src':'6.png'},{'src':'7.png'},
            {'src':'8.png'},{'src':'9.png'},{'src':'10.png'},{'src':'11.png'},{'src':'12.png'},{'src':'13.png'},{'src':'14.png'}]
            }
          var isArrive= false;//防止多次滾動重復數據
              if(checkScroll() && !isArrive){
                  var oParent = document.getElementsByClassName('content')[0];
                  for(var i =0;i<dataInt.data.length;i++){
                      isArrive=true;
                      var oDiv =document.createElement('div');//添加元素節點
                      oDiv.className ='item';
                      oDiv.innerHTML ='![](./img/'+dataInt.data[i].src+')'
                      oParent.appendChild(oDiv);                    
                  }
                  isArrive = false;
                  waterFull()
              }
          } 

     function checkScroll(){
             var   oParent = document.getElementsByClassName('content')[0];
             var   aDiv =oParent.getElementsByClassName('item');
             var   lastPinH=aDiv[aDiv.length-1].offsetTop+Math.floor(aDiv[aDiv.length-1].offsetHeight/2); 
             //創建【觸發添加塊框函數waterfall()】的高度:最后一個塊框的距離網頁頂部+自身高的一半(實現未滾到底就開始加載)
             var   scrollTop=$(window).scrollTop();//滾動高度
             var   winndowHeight=$(window).height(); //頁面高度
             return   (lastPinH<scrollTop+winndowHeight)? true : false ; //到達指定高度后 返回true,觸發waterfall()函數
        }
     return {
              init:init
          }
     })()
     
     WaterFull.init();

  • 原生js代碼
  function waterFull(){
             var Oparent = document.getElementById('main');
             var aPin =Oparent.getElementsByClassName('pin')//獲取存儲塊pin的數組;
             var num =Math.floor(document.documentElement.clientWidth/aPin[0].offsetWidth)//獲取窗口每行能容納的個數
            
             var pinHArr=[];//用于存儲 每列中的所有塊框相加的高度
             for(var i =0 ; i<num;i++){
                 pinHArr[i]=0;
             }
             for(var i =0 ; i<aPin.length;i++){
                
                     //獲取PinHArr的最小值;
                     var minValue =Math.min.apply(null,pinHArr);
                     //獲取pinHArr最小值得索引;
                     var minIndex = pinHArr.indexOf(minValue);
                       
                         aPin[i].style.top=minValue+'px';//用定位改變其top值
                         aPin[i].style.left=aPin[minIndex].offsetWidth*minIndex+'px';//用定位改變其left值
                        
                     
                     pinHArr[minIndex] += aPin[i].offsetHeight;//更改添加后列的高度
                 }
             }
  • css瀑布流效果:
20170404_221332.gif
  • 關于css瀑布流:
    方法有許多種,優缺點都有,但是本人建議用js或者jquery;因為畢竟是要向后端mock數據所以css布局不建議使用;就給出css3方法其中一種代碼
     <style>
        *{padding:0;margin:0;}
        .clearfix:after,
        .clearfix:before {
        content: " ";
        display: table;
        }
        .clearfix:after {
        clear: both;
        }
        .main {
        position: relative;
        -webkit-column-width: 222px;
        -moz-column-width: 222px;
        /*column-width 屬性規定列的寬度。*/
        -webkit-column-gap: 5px;
        /*column-gap 屬性規定列之間的間隔。*/
        -moz-column-gap: 5px;
        }
        .box {
        float: left;
        padding: 15px 0 0 15px;
        transition: all 1s;
        }
        .box .pic {
            width: 200px;
            height: auto;
            padding: 10px;
            border-radius: 5px;
            box-shadow: 0 0 5px #cccccc;     
        }            
       .box .pic img {
               display: block;
               width: 100%;
        }
  • css3瀑布流布局:
    我們將要用到的是CSS3新加的column屬性,通過指定容器的列個數column-count,列間距column-gap,列中間的邊框(間隔邊線)column-rule,列寬度column-width實現。

    優點:
    1. 直接用CSS定義,方便快捷,是最好不過了;
    2. 擴展方便。

    缺點:
    1. 目前仍有部分瀏覽器不支持CSS3;
    2.CSS3這種方式的數據排列是從上到下排列到一定高度后,再把剩余元素依次添加到下一列;

2.木桶布局

  • 思路:

1.當圖片加載進來時,初始化new的image對象,給圖片定一個高度;獲取等比例下的寬度;
2.把圖片的寬高放入一個空數組,通過循環數組獲取圖片的總寬度;
3.拿獲取的總寬度跟容器寬度相比較,如果總寬度大于容器寬度,那就拿出最后一個圖片的寬度,直到總寬度小于容器的寬度。然后拉伸容器里的圖片讓,圖片填充這個容器的寬度(獲取容器里現在的最后高度)
4.再把數組清空,放入剛才被拿出的最后放不下那一項(重置數組總寬度)
5.寫一個函數渲染每排圖片(把新高度傳入進去)。

  • 難點
1.當圖片加載進來時,初始化new的image對象,給圖片定一個高度;獲取等比例下的寬度;
loadImg:function(){//構建url就是一個接口;也可以是ajax;
                  var _this = this //保存作用于的this
                  var imgUrls = this.getImgUrls(40);//如果是ajax是不可能根據圖片地址獲取他的寬高的

                 $.each(imgUrls,function(idx,url){//所以循環這個數組,
                      var  img = new Image();//創建一個圖片對象;
                      img.src =url;
                      img.onload =function(){                  
                          var imgInfo ={
                              target:$(img),//哪一張圖片
                              width:200*(img.width/img.height),//  x/200=img.width/img.height
                              height:200//高度設為200;

                          }
                          _this.render(imgInfo);
                      }
                  })

               },




2.把圖片的寬高放入一個空數組,通過循環數組獲取圖片的總寬度;
  render: function(imgInfo){
     
     
      var clientWidth = this.$ct.width();
      var rowWidth = 0;
      var newRowHeight = 0;
      var lastImgInfo = imgInfo;

      this.rowList.push(imgInfo);
      for(var i=0; i< this.rowList.length; i++){
         rowWidth = rowWidth + this.rowList[i].width;
      }


3.那獲取的總寬度跟容器寬度相比較,如果總寬度大于容器寬度,那就拿出最后一個圖片的寬度,直到總寬度小于容器的寬度。然后拉伸容器里的圖片讓,圖片填充這個容器的寬度(獲取容器里現在的最后高度)

 if(rowWidth > clientWidth){
        this.rowList.pop();
        rowWidth = rowWidth-lastImgInfo.width//目前每行的寬度;
        newRowHeight = clientWidth*200/rowWidth;
        //   rowWidth/200   ==  clientWidth/ X

      
      

4.再把數組清空,放入剛才被拿出的最后放不下那一項(重置數組總寬度)
         this.rowList = [];
        this.rowList.push(imgInfo);
        this.layout(newRowHeight);

5.寫一個函數渲染每排圖片(把新高度傳入進去)
 layout: function(newRowHeight){
      console.log('createRow');
      var $rowCt = $('<div class="img-row"></div>');
      $.each(this.rowList, function(idx, imgInfo){
        var $imgCt = $('<div class="img-box"></div>'),
            $img = $(imgInfo.target);
            $img.height(newRowHeight);
            $imgCt.append($img);
            $rowCt.append($imgCt);
      });
      this.$ct.append($rowCt);

  • 效果:
20170404_222754.gif

3.等高布局

  • 思路:等高布局有幾種不同的方法如定位,但目前為止我認為瀏覽器兼容最好最簡便的應該是padding補償法。首先把列的padding-bottom設為一個足夠大的值,再把列的margin-bottom設一個與前面的padding-bottom的正值相抵消的負值,父容器設置超出隱藏,這樣子父容器的高度就還是它里面的列沒有設定padding-bottom時的高度,當它里面的任一列高度增加了,則父容器的高度被撐到它里面最高那列的高度,其他比這列矮的列則會用它們的padding-bottom來補償這部分高度差。因為背景是可以用在padding占用的空間里的,而且邊框也是跟隨padding變化的,所以就成功的完成了一個障眼法。

  • 重點:

.wrap{         
            overflow: hidden;//父容器設置超出隱藏,這樣子父容器的高度就還是它里面的列沒有設定padding-bottom時的高度
        }
   .left{
            float: left;
            padding-bottom: 10000px;
            margin-bottom: -10000px;
        }
        .right{
            float: right;
            padding-bottom: 10000px;
            margin-bottom: -10000px;                          
        }
  • 看下效果:
20170404_165914.gif
  • 代碼
<style>
        .wrap{
            width:100%;
            background:#ccc;
            overflow: hidden;
            min-width: 600px;
           
        }
        .left{
            width:300px;
            float: left;
            padding-bottom: 10000px;
            margin-bottom: -10000px;
            background: red;
            text-align: center;
            border: 1px saddlebrown solid;
        }
        .right{
            width:300px;
            float: right;
            padding-bottom: 10000px;
            margin-bottom: -10000px;
            background:green;
            text-align: center;
            border: 1px saddlebrown solid;
            
            
        }
        h2{
            padding: 10px;
        }
    </style>
</head>
<body>
    <div class="wrap">
        <div class="left">
           ![](./img/1.png)
           
        </div>
        <div class="right">
           ![](./img/2.png)
        </div>
    </div>
   <button class="btn1">左側欄增加高度</button>
   <button class="btn2">右側欄增加高度</button>
    <script src="jquery-3.2.0.min.js"></script>
    <script>
          $('.btn1').on('click',function(){
              $('.left').append('![](./img/1.png)')
          })
          $('.btn2').on('click',function(){
              $('.right').append('![](./img/2.png)')
          })
    </script>
</body>

4. 圣杯布局

  • 思路:
    圣杯布局解決的問題是兩邊頂寬,中間自適應的三欄布局,中間欄要在放在文檔流前面以優先渲染。圣杯布局的三欄全部float浮動,但左右兩欄加上負margin讓其跟中間欄div并排,以形成三欄布局。解決”中間欄div內容不被遮擋“問題的思路:圣杯布局,為了中間div內容不被遮擋,將中間div設置了左右padding-left和padding-right后,將左右兩個div用相對布局position: relative并分別配合right和left屬性,以便左右兩欄div移動后不遮擋中間div。

  • 重點:

        div{
             float:left;
         }
    .wrap
    {
        padding-right: 100px;//空出左右位置給左右兩欄;
        padding-left:100px
    }
    .left
    {
        margin-left: -100%;//左邊欄與中間攔并排;
        position: relative;
        left: -100px;//左邊的div寬度大小;
    }
    .right
    {
        margin-left: -100px;//右邊欄與中間攔并排;大小為右邊欄寬度;
        position: relative;
        left: 100px;//左邊的div寬度大小;
    }
  • 看下效果:
20170404_172951.gif
  • 代碼
 <style>
        .wrap{
            border: 1px saddlebrown solid;
            padding-left:100px;
            padding-right: 100px;
            min-width: 600px;
        }
        .clear:after{
            content:'';
            display: block;
            clear:both;
        }
        .main{
            width:100%;
            height: 200px;
            float:left;
            background:red;
        }
        .left{
            float: left;
            width:100px;
            height: 100px;
            background:green;
            margin-left: -100%;
            position: relative;
            left: -100px;

        }
       .right
               {
        float: left;
        width: 100px;
        height: 100px;
        background: pink;
        margin-left: -100px;
        position: relative;
        left: 100px;
        

    }
    </style>
</head>
<body>
     <div class="wrap clear">
        <div class="main"></div>
        <div class="left"></div>
        <div class="right"></div>
    </div>
</body>

5.雙飛翼布局:

  • 思路:
    圣杯布局和雙飛翼布局解決的問題是一樣的,就是兩邊頂寬,中間自適應的三欄布局,中間欄要在放在文檔流前面以優先渲染。圣杯布局和雙飛翼布局解決問題的方案在前一半是相同的,也就是三欄全部float浮動,但左右兩欄加上負margin讓其跟中間欄div并排,以形成三欄布局。不同在于解決”中間欄div內容不被遮擋“問題的思路不一樣;雙飛翼布局:為了中間div內容不被遮擋,直接在中間div內部創建子div用于放置內容,在該子div里用margin-left和margin-right為左右兩欄div留出位置。

  • 重點:

       .main
       {
        width: 100%;
        float: left;
       }
       .main .mainer//在中間div內部創建子div用于放置內容,在該子div里用margin-left和margin-right為左右兩欄div留出位置
    {
        margin-left: 120px;
        margin-right: 120px;
    }
       .left
        {
            float: left;
            margin-left: -100%; //左邊欄與中間攔并排;
        }
        .right
        { 
            float: left;
            margin-left: -100px; //右邊欄與中間攔并排
        }
  • 看下效果:
20170404_174837.gif
  • 代碼:
 .wrap
        {
            border: 1px saddlebrown solid;
            min-width: 600px;
        }
        .clear:after
       {
        content: "";
        display: block;
        clear: both;
       }
       .main
       {
        width: 100%;
        height: 200px;      
        float: left;
     

       }
       .main .mainer
    {
        background: black;
        height: 200px;
        margin-left: 120px;
        margin-right: 120px;

    }
       .left
        {
            width:100px;
            height: 100px;
            background:green;
            float: left;
            margin-left: -100%;
            
        }
        .right
        {
            width: 100px;
            height: 100px;
            background: pink;
            float: left;
            margin-left: -100px;
            
        }

    </style>
</head>
<body>
    <div class="wrap clear">
        <div class="main">
            <div class="mainer"></div>
        </div>
        <div class="left"></div>
        <div class="right"></div>
    </div>
</body>
  • 圣杯雙飛翼的區別:

圣杯布局和雙飛翼布局解決的問題是一樣的,就是兩邊頂寬,中間自適應的三欄布局,中間欄要在放在文檔流前面以優先渲染。圣杯布局和雙飛翼布局解決問題的方案在前一半是相同的,也就是三欄全部float浮動,但左右兩欄加上負margin讓其跟中間欄div并排,以形成三欄布局。不同在于解決”中間欄div內容不被遮擋“問題的思路不一樣:圣杯布局,為了中間div內容不被遮擋,將中間div設置了左右padding-left和padding-right后,將左右兩個div用相對布局position: relative并分別配合right和left屬性,以便左右兩欄div移動后不遮擋中間div。雙飛翼布局,為了中間div內容不被遮擋,直接在中間div內部創建子div用于放置內容,在該子div里用margin-left和margin-right為左右兩欄div留出位置。

6. Flex布局:

Flex布局也是很常用的布局方法可以點擊鏈接去了解下Flex布局方法用法.
Flex布局

7.最后看下jquery實戰-無限加載-jsonp-瀑布流

20170405_222202.gif

瀑布流
木桶
等高
圣杯
雙飛翼

jquery實戰-無限加載-jsonp-瀑布流

希望對給位朋友有所幫助~~~
版權歸饑人谷__楠柒所有,如要轉載請請注明出處~

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,837評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,196評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,688評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,654評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,456評論 6 406
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,955評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,044評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,195評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,725評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,608評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,802評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,318評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,048評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,422評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,673評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,424評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,762評論 2 372

推薦閱讀更多精彩內容