1. 濟(jì)寧果殼科技專業(yè)軟件開發(fā)團(tuán)隊(duì),提供全方位的互聯(lián)網(wǎng)服務(wù)!
          座機(jī):15563775221 手機(jī):15563775221(微信)

          熱門標(biāo)簽

          1. 首頁
          2. 果殼學(xué)院
          3. 濟(jì)寧網(wǎng)站建設(shè)
          4. Pinterest 瀑布布局是怎么實(shí)現(xiàn)的?
          Pinterest 瀑布布局是怎么實(shí)現(xiàn)的?

          Pinterest 瀑布布局是怎么實(shí)現(xiàn)的?

          瀑布流是很多很常用的一種布局模式 瀑布流布局已成為當(dāng)今非常普遍的圖片展示方式,無論是PC還是手機(jī)等移動設(shè)備上。這種布局圖片的樣式大概分為三種:等高等寬、等寬不等高、等高不等寬,接下來我們就最為普遍的等寬不等高形式來作為示例。

          濟(jì)寧果殼科技

          2017-12-16 16:34:53

          0

          4141

          瀑布流形式的圖片布局方式在手機(jī)等移動端設(shè)備上運(yùn)用廣泛,比較常見的是下面前兩種:


          一、等寬等高

          613712-20160617220117370-1637450890.png

          這種形式實(shí)現(xiàn)起來非常容易,這里就不再多說。



          二、等寬不等高

          613712-20160617220141979-2044210515.png

          這種形式算是比較正統(tǒng)的瀑布流布局形式

          可以看到,它里面實(shí)際是若干個(gè)等寬的列容器,通過計(jì)算將圖片push到不同的容器里。而本文介紹的展示方法是通過定位的方式,雖然最后布局展示的方式不同,但之前的算法都比較類似



          <div class="box">
              <img class="img" src="./resource/images/1.jpg" />
              <div class="desc">Description</div>
          </div>
          <div class="box">
              <img class="img" src="./resource/images/2.jpg" />
              <div class="desc">Description</div>
          </div>
          <div class="box">
              <img class="img" src="./resource/images/3.jpg" />
              <div class="desc">Description</div>
          </div>


          得到如下效果:


          613712-20151029142811513-324142989.png

          接下來:



          var boxArr = $('.box'),
            num = Math.floor(document.body.clientWidth / boxArr.eq(0).outerWidth(true)),
               columnHeightArr = [];
          columnHeightArr.length = num;
          boxArr.each(function(index, item) {
              if (index < num) {
                  columnHeightArr[index] = $(item).position().top + $(item).outerHeight(true);
              } else {
                  var minHeight = Math.min.apply(null, columnHeightArr),
                      minHeightIndex = $.inArray(minHeight,columnHeightArr);

                  $(item).css({
                      position: 'absolute',
                      top: minHeight,
                      left: boxArr.eq(minHeightIndex).position().left
                  });
              }
          });


          以上代碼大意為:

          1. 首先計(jì)算出在瀏覽器中一行能容納多少圖片 (num) ,注意這里用了outerWidth,當(dāng)傳入true時(shí)會返回元素包括margin、padding、border全部盒模型屬性的尺寸;

          2. 創(chuàng)建一個(gè)存儲每一列高度的數(shù)組 (columnHeightArr) ,該數(shù)組的長度即為num值;

          3. 遍歷所有圖片,將第一行的圖片高度分別存入列高數(shù)組中 (columnHeightArr) ,從第二行開始,首先計(jì)算出所有列中最小的高度 (minHeight) 以及最小高度所在的列 (minHeightIndex)。之后將第二行開始的圖片定位在高度最小列的下面,效果如下:



          可以看到雖然擺對了地方但是所有的圖片都放在同一個(gè)地方了,這是因?yàn)槲覀冃枰跀[放一張圖片后就要增加該列的高度:




          var boxArr = $('.box'),
              num = Math.floor(document.body.clientWidth / boxArr.eq(0).outerWidth(true)),
              columnHeightArr = [];
          columnHeightArr.length = num;

          boxArr.each(function(index, item) {
          if (index < num) {
          columnHeightArr[index] = $(item).position().top + $(item).outerHeight(true);
          } else {
          var minHeight = Math.min.apply(null, columnHeightArr),
                     minHeightIndex = $.inArray(minHeight, columnHeightArr);

          $(item).css({
                   position: 'absolute',
                   top: minHeight,
                   left: boxArr.eq(minHeightIndex).position().left
                 });

          columnHeightArr[minHeightIndex] += $(item).outerHeight(true);
          }
          });

          結(jié)果正確:




          注意:上面的代碼需要運(yùn)行于window.onload方法里,因?yàn)橹挥挟?dāng)頁面中的圖片資源全部加載完畢后,其每張圖片的高度才會有效。

          因此會有一些很嚴(yán)重的問題,當(dāng)網(wǎng)絡(luò)不好的時(shí)候圖片沒有完全加載完成就會出現(xiàn)圖片展示不全高度缺失的情況,這點(diǎn)在移動端很明顯。而且當(dāng)我們加載更多時(shí),更難判斷新追加的圖片是否加載完成。

          在實(shí)際生產(chǎn)中更不會有一開始就將圖片寫死在HTML中的情況,所以我們通常用以下的方式來做:

          首先我們在獲得圖片地址時(shí)同時(shí)也需要獲取圖片的寬和高 ,這點(diǎn)對服務(wù)端后臺來說并不是什么難事,可以拜托后臺兄弟將圖片的寬高數(shù)據(jù)拼進(jìn)JSON,傳遞給你;

          *接下來介紹小技巧,是一個(gè)朋友教我的,非常實(shí)用,它能保證一個(gè)元素?zé)o論大小如何變化,比例始終保持一致。這個(gè)技巧尤其適用于移動端,因?yàn)樵貫榱隧憫?yīng)式通常使用百分比的形式。

          假如手機(jī)頁面中有一張圖片,其寬度要為屏幕的一半,高寬比為2:1,需要在任何分辨的手機(jī)上保持比例不變。如何做?給元素設(shè)置如下屬性:

          .box { width: 50%; height: 0; padding-bottom: 100%;
          }

          不設(shè)置高度,而是用padding“擠”出元素高度,而padding的百分比值都是基于父級容器的寬度。padding需要擠多少呢?就是寬度乘以高寬比(width和padding值均為百分比值),這就是我們?yōu)槭裁葱枰@得圖片尺寸的原因。

          效果:




          可以看到在chrome手機(jī)模擬器中ipone4和腎6Plus的顯示效果是完全一樣的。在手機(jī)頁面中寬是固定的,而高會隨著頁面內(nèi)容的多少而變化,這個(gè)技巧利用元素padding百分比的值其實(shí)是基于其父級容器的寬,將高的值巧妙的轉(zhuǎn)化成與寬相關(guān)。

          說到現(xiàn)在可能有人終于忍不住要問了,講了這么多和瀑布流有什么關(guān)系!簡單就是一句話,我們要拋棄 img 標(biāo)簽,而采用背景圖的方式。為了使用背景圖,就得保持元素的比例永遠(yuǎn)與圖片保持一致。

          通過這種方式,可以不用判斷圖片都加載完畢,直接產(chǎn)生一些與圖片同比例的div,再為其設(shè)置背景圖,如下:



          這里比如最外層的box寬度為220px,里面的img元素寬度就可以為100%,高度就可以通過padding擠出了。




          懶加載

          使用背景圖的方式還有好處那就是可以比較方便的實(shí)現(xiàn)懶加載。那什么是懶加載呢?就是當(dāng)元素在我們的視野中時(shí)才展示圖片,滾動時(shí)屏幕下方的圖片并不展示,這可以很好的增加加載速度提升體驗(yàn)。

          首先我們給最外層的box增加一個(gè)box-item類名(之后有用),將圖片url并不設(shè)置給backgroundImage屬性,而是賦給一個(gè)自定義屬性:data-src。

          <div class="box box-item"> <div class="img" data-src="./resource/images/1.jpg"></div> <div class="desc">Description</div> </div>
          接下來我們編寫懶加載函數(shù):





          function lazyLoad() {
          var boxArr = $('.box-item');
          boxArr.each(function(index, item) {
          var viewTop = $(item).offset().top - $(window).scrollTop(),
                     imgObj = $(item).find('.img');
                 if ((viewTop < $(window).height()) && (($(item).offset().top + $(item).outerHeight(true)) > $(window).scrollTop())) {
                   imgObj.css('backgroundImage','url('+imgObj.attr("data-src")+')').removeClass('data-src');
                   $(item).removeClass('box-item');
                 }
             })}



          首先我們獲取所有擁有 .box-item 類名的元素,遍歷。viewTop 為圖片相對于瀏覽器窗口的相對高度,類似于position:fixed感覺。

          通過條件進(jìn)行判斷,只有當(dāng)該圖片在瀏覽器窗口內(nèi)(之上或之下都不行)時(shí),將需要設(shè)置背景圖元素的 data-src 值展示出來,并刪除該屬性。

          之后將最外層元素的 box-item 刪除,因?yàn)橐呀?jīng)展示出來的圖片不需要再進(jìn)行這些判斷,刪除了該類名下一次滾動時(shí)就不會獲取到已經(jīng)展示過的元素,需要遍歷的次數(shù)就會越來越少,這樣能起到一個(gè)優(yōu)化的作用。

          該函數(shù)需要在你的元素已經(jīng)append進(jìn)頁面時(shí)調(diào)用,以及在滾動時(shí)調(diào)用:

          lazyLoad();
          $(window).scroll(lazyLoad);
          
          
          
          

          滾動加載

          說完了懶加載,再說說滾動加載。所謂滾動加載就是當(dāng)頁面滾動到底部附近時(shí)加載新的圖片。我這里選擇的是滾動到高度最小的列底部時(shí)加載新的數(shù)據(jù),你也可以根據(jù)自己的喜好來做判斷。


          function scrollLoad() {
          var viewHeight = $(window).scrollTop() + $(window).height(),
                  minHeight = Math.min.apply(null, columnHeightArr);

          if (viewHeight >= minHeight) {
               //loadMore...  }}


          說完了PC端,我們來說下手機(jī)端。其實(shí)原理是一樣的,只是從多列變成固定的兩列了。




          var boxArr = $('.box'),
              columnHeightArr = [];
          columnHeightArr.length = 2;

          boxArr.each(function(index, item) {
          if (index < 2) {
          columnHeightArr[index] = $(item).position().top + $(item).outerHeight(true);
          } else {
          var minHeight = Math.min.apply(null, columnHeightArr),
                     minHeightIndex = $.inArray(minHeight, columnHeightArr);

          $(item).css({
                   position: 'absolute',
                   top: minHeight,
                   left: boxArr.eq(minHeightIndex).position().left
                 });

          columnHeightArr[minHeightIndex] += $(item).outerHeight(true);
          }
          });



          不同的是為了適應(yīng)不同屏幕的手機(jī),最外層的box容器寬度和邊距要設(shè)置成百分比的形式。


          最后有一點(diǎn)要注意,因?yàn)槲覀儧]有像百度一樣用一個(gè)個(gè)列盒子去裝,而是用定位的方式。導(dǎo)致的問題是圖片元素的父級沒法自適應(yīng)高度,如果你有相關(guān)的需求我們可以計(jì)算出所有列中最長的長度,并將這個(gè)值賦值給父容器的min-height屬性:

          $('body').css('minHeight',Math.max.apply(null, columnHeightArr));




          整理下完整的代碼,瀑布流的全套服務(wù)就到這了 :)


          var dataArr = [
                  {picUrl:'./resource/images/1.jpg',width:522,height:783},
                  {picUrl:'./resource/images/2.jpg',width:550,height:786},
                  {picUrl:'./resource/images/3.jpg',width:535,height:800},
                  {picUrl:'./resource/images/4.jpg',width:578,height:504},
                  {picUrl:'./resource/images/5.jpg',width:1440,height:900}
              ];

              $.each(dataArr, function(index, item) {
                  $("body").append('<div class="box box-item">' +
                                      '<div class="img" style="height:0;padding-bottom:'+cRate(item) * 100 + "%"+'" data-src="'+item.picUrl+'"></div>' +
                                      '<div class="desc">Description</div>' +
                                   '</div>');
              });

              var boxArr = $('.box'),
                  num = Math.floor(document.body.clientWidth / boxArr.eq(0).outerWidth(true)),
                  columnHeightArr = [];
              columnHeightArr.length = num;
              
              arrangement();  $('body').css('minHeight',Math.max.apply(null, columnHeightArr));

              lazyLoad();

              function arrangement() {
                  boxArr.each(function(index, item) {
                      if (index < num) {
                          columnHeightArr[index] = $(item).position().top + $(item).outerHeight(true);
                      } else {
                          var minHeight = Math.min.apply(null, columnHeightArr),
                              minHeightIndex = $.inArray(minHeight, columnHeightArr);
                          $(item).css({
                              position: 'absolute',
                              top: minHeight,
                              left: boxArr.eq(minHeightIndex).position().left
                          });
                          columnHeightArr[minHeightIndex] += $(item).outerHeight(true);
                      }
                  });
              }

              function lazyLoad() {
                  var boxArr = $('.box-item');
                  boxArr.each(function(index, item) {
                      var viewTop = $(item).offset().top - $(window).scrollTop(),
                          imgObj = $(item).find('.img');
                      if ((viewTop < $(window).height()) && ($(item).offset().top + $(item).outerHeight(true) > $(window).scrollTop())) {
          //                console.log($(item).attr('data-src'));
                          imgObj.css('backgroundImage','url('+imgObj.attr("data-src")+')').removeClass('data-src');
                          $(item).removeClass('box-item');
                      }
                  })
              }

              function cRate(obj) {
                  return obj.height / obj.width;
              }

              function scrollLoad() {
                  var viewHeight = $(window).scrollTop() + $(window).height(),
                      minHeight = Math.min.apply(null, columnHeightArr);
                  if (viewHeight >= minHeight) {
                      //loadMore...
                  }
              }

              $(window).scroll(function() {
                  lazyLoad();
                  scrollLoad();
              });


          感謝您的瀏覽,希望能給您帶來幫助。


          濟(jì)寧網(wǎng)站建設(shè),濟(jì)寧微信公眾號開發(fā),濟(jì)寧seo優(yōu)化推廣,濟(jì)寧手機(jī)APP開發(fā),濟(jì)寧微商城開發(fā),濟(jì)寧做網(wǎng)站,濟(jì)寧網(wǎng)絡(luò)公司,濟(jì)寧果殼科技


          定制首選 果殼科技 咨詢熱線:0537-2551991

          關(guān)閉咨詢框
          中文字幕亚洲日韩精品一区无码,欧美国产精品,人妻一级无码中文字幕,国产1024永久免费