天天看點

玩轉Masonry JS庫來實作瀑布流Web效果

工作項目中需要制作個Mobile上的Web App的展示,友善快捷通路和評價回報。在展示頁面能看到應用展示圖,點選進入Web應用。我不是前端開發者,對HTML, CSS, JS這三劍客僅僅是略知一二。于是先規劃了個簡單的設計,感覺瀑布流的圖檔展示方式比較美觀,同時布局的高度也一定靈活性。就按照Pinterest Android/IOS和花瓣Mobile Web App的目标開始實作。

第一天的成果是完成了基本的展示和連結。在iPhone模拟器上效果如下

玩轉Masonry JS庫來實作瀑布流Web效果

HTML頁面代碼snippet:

<script type="text/javascript" src="js/masonry-docs.min.js"></script>




   

  
   
                聯想3C服務


        
玩轉Masonry JS庫來實作瀑布流Web效果
玩轉Masonry JS庫來實作瀑布流Web效果
<script type="text/javascript" src="assets/jquery.min.js"></script> <script type="text/javascript" src="assets/topsrh.min.js"></script> <script type="text/javascript" src="assets/jquery.qrcode-0.7.0.min.js"></script> <script type="text/javascript" src="assets/cases.min.js"></script>

相對應的CSS,比較關鍵的width的值,它決定了horizontal的column數目,比如這裡的45%, 略小于50%, 也就是橫向上可容納兩列:

.hero-item,
.hero-masonry .grid-sizer {
  width: 45%; /* juse a lil under  47 */
  margin: 3% 2%;
  /*float: middle ;*/
  border-radius: 8px;
  box-shadow: 0 1px 3px rgba(0,0,0,.3);
  -moz-box-shadow: 0 1px 3px rgba(0,0,0,.3);
  -webkit-box-shadow: 0 1px 3px rgba(0,0,0,.3);
}
           

這時有個layout問題會随機出現,縱向的layout有時會讓每個展示層疊在一起。就像下面的這樣:

玩轉Masonry JS庫來實作瀑布流Web效果

縱向的layout問題在第一次通路的時候比較容易出現,之後如果重新整理一兩次一般就恢複正常了。

原因來自于圖檔的<img>元素并沒有指定的height。我們希望瀑布流的各個高度能夠靈活展示,并由浏覽器的布局計算得出。但是浏覽器加載圖檔與layout計算的異步操作令這裡留下了出錯的可能。也就是說,圖檔必須先load完成之後,浏覽器才能根據圖檔的natural size得出為這個<img>留下的layout的高度。而load圖檔的時間晚于layout計算就出現了這樣的問題,浏覽器以default的height來做布局。

W3School上的文檔對<img>元素的width, height有這樣的說明,建議盡量指定width, height。http://www.w3school.com.cn/html5/att_img_width.asp 。 但是像其它任何程式設計中一樣,hard code帶來的并不是最好的解決方法。有沒有讓我們靈活的計算<img>的height屬性,并控制layout的方法呢?

請教了前端工程師朋友,找到了Masonry庫的layout和sizing的方法,以及如何取得masonry instance的方法。

這樣,解決方法是在<img>的onload()事件中調用masonry的layout()方法。這裡注意的是masonry的instance是通過Masonry.data()這個方法取得的。data()這個方法是Masonry的,而不是masonry instance的方法。 代碼如下:(官方文檔 http://masonry.desandro.com/methods.html。)

<script>
    $(function(){
        var imgs = $("img");
        for(var i=0,len=imgs.length;i
  
   的onload()中執行layout()
            imgs[i].onload = function(){
                msnry.layout();
            }
        }
    });
</script>

  
           

問題解決!!

繼續閱讀