瀑布流佈局(基於多欄列表流體佈局實現)

轉在前面:(淘寶UED

3) 絕對定位。即 Pinterest ,Mark之,KISSY 採用的方式:
html

  • 可謂是最優的一種方案,方便添加數據內容,窗口變化,列數/數據塊都會自動調整;
  • 線上例子

缺點:git

  • 須要實現知道數據塊高度,若是其中包含圖片,須要知道圖片高度;
  • JS 動態計算數據塊位置,當窗口縮放頻繁,可能會狂耗性能。

KISSY.Waterfall 實現思路

KISSY 的 Waterfall 組件主要包含兩個部分,一個是對現有數據塊進行排列計算各自所在的位置; 二是下拉滾動時,觸發加載數據操做,並把數據添加到目標容器中。github

1) 數據塊排列,算法步驟簡述下:算法

  • 初始化時,對容器中已有數據塊元素進行第一次計算,須要用戶給定: a,容器元素 — 以此獲取容器總寬度; b,列寬度; c,最小列數; 最終列數取的是容器寬度/列寬度和最小列數的最大值,這樣保證了,當窗口很小時,仍然出現最小列數的數據;
  • 得到列數後,須要保存每一個列的當前高度,這樣在添加每一個數據塊時,才知道起始高度是多少;
  • 依次取容器中的全部數據塊,先尋找當前高度最小的某列,以後根據列序號,肯定數據塊的left,top值,left 爲所在列的序號乘以列寬,top 爲所在列的當前高度,最後更新所在列的當前高度加上這個數據塊元素的高度,至此,插入一個元素結束;
  • 當全部元素插入完畢後,調整容器的高度爲各列最大的高度值,結束依次調整;
  • 性能效率上的注意點: a,若是當前正在調整中,又觸發了 resize 事件,須要將上次調整暫停後執行此次調整(見 timedChunk 函數); b,resize 觸發會很頻繁,能夠將回調函數緩存一段時候後執行,即當這段時間內屢次觸發了resize事件,但回調函數只會執行一次(見 S.buffer 函數)
  • 感興趣的能夠參見源碼

2) 異步加載數據,前面講的是如何對容器中已有元素進行排列,但不少狀況下,還須要不斷加載新數據塊,爲此專門設計了一個獨立的模塊 KISSY.Waterfall.Loader,其實這個功能就更簡單了,僅包含兩個步驟:api

  • 綁定滾動事件,並肯定預加載線高度值,即滾動到哪一個高度後,須要去加載數據,其實這個就是列的最小高度值,這樣當前滾動值和最小高度值比較一下便可判斷出來,是否要觸發加載數據;
  • 加載數據,爲了避免對數據源作太多限制,徹底由使用者本身決定數據源從哪邊獲取和其格式,這樣更好的方便用戶使用。爲此,該組件只提供一個 load(success,end) 接口,怎樣load 由用戶本身去定義,而其中的 success/end,分別給出如何添加新數據(suceess 即同 addItems)/如何中止加載的接口。這樣真是太方便了~~
  • 感興趣的能夠參見源碼

KISSY.Waterfall 示例和文檔

看到這邊,是否是很想試用一下~~ 嗯嗯,這裏給出一些相關學習資料和示例,以供參考:瀏覽器

歡迎試用和提出意見~~緩存

2、稍稍要緊的話

跟風,尤爲受pinterest的煽風點火,瀑布流如今很多人關注。我正好最近比較閒,加上有人曾在我站點提出但願我介紹點瀑布流的東西,因此,今兒個也隨下大流。app

pinterest以及上面迅雷UED xwei的瀑布流demo(至少在FireFox下仍是有致命的顯示bug的)都是採用的絕對定位實現的,有相對複雜的位置計算。異步

我一貫不喜歡吃別人嚼過的米飯,因而嘗試使用另外的原理實現。我是個流體佈局控,對絕對定位啊、浮動啊什麼的一貫沒什麼好感,因而,這裏要介紹的就是基於多欄列表流體佈局實現的瀑布流佈局效果。函數

大體結構、佈局見下面的手繪圖:
流體佈局下的瀑布流結構草圖 張鑫旭-鑫空間-鑫生活

沒有複雜的位置計算,不須要知道里面元素的高度以及寬度,且易理解,關鍵是具體實現~~

3、高潮來了:demo展現

您能夠狠狠地點擊這裏:基於多欄列表瀑布流佈局demo

瀑布流demo頁面效果截圖 張鑫旭-鑫空間-鑫生活

歡迎各類滾動,縮放等測試。低版本IE瀏覽器也是兼容滴。問題嘛也是有滴,就是滾動到必定位置再F5刷新的時候,部分加載的內容有丟失,須要從新滾 動加載。這個嘛,我我的以爲小小demo,不必折騰啦(實際上要實現也比較容易,改動以下:每次滾動不是append一個節點,而是連續回調直到加載到 屏幕下方。不懂什麼意思?花點功夫看看JS實現原理就會明白了)~~

4、說說原理

第一次進入的時候,根據瀏覽器寬度以及每列寬度計算出列表個數,而後無論三七二十一,每列先加載個5張圖片再說。

當滾動的時候,對每一列的底部位置作檢測,若是在屏幕中或屏幕上方,則當即append一個新圖片(注意:爲了簡化代碼,提升性能,同時便於演示等,這裏只append了一個)。由於,滾動時連續的,所以,咱們實際看到的效果是圖片不斷load出來。

當瀏覽器寬度改變的時候,頁面上有個idwaterFallDetectspan標籤,這個標籤做用有兩個:一是實現兩端對齊效果,二是用來檢測瀑布流佈局是否須要刷新。

檢測原理以下:
span標籤寬度與一個列表寬度一致,當瀏覽器寬度變小的時候,若是小到必定程度,顯然,瀏覽器最右邊的列表就會跑到下一行,把空span擠到後面去,空span發生較大的水平位移,顯然,能夠通知腳本,佈局須要刷新;當瀏覽器寬度變大的時候,若是變大的尺寸超過一列的寬度,顯然,這個空span灰跑到第一行去,一樣是發生較大的水平位移,所以,又能夠通知腳本刷新瀑布流佈局了。

這個方法的好處是幾乎沒有計算就能夠一點不差地知道什麼時候瀑布流佈局須要刷新。這顯然要比設置resize定時器+位置尺寸計算要簡單高性能地多。

瀏覽器寬度變小時觸發瀑布流更新的原理示意 瀏覽器寬度變寬時觸發的瀑布流更新原理示意

滾動時的頁面刷新是基於HTML字符串的處理,而不是更改每一個DOM元素的位置(這是絕對定位實現的處理),所以,這裏的效率顯然更高。

5、總結:基於多欄列表流體佈局瀑布流效果優勢

  1. 簡單:最大限度利用了瀏覽器的流體特性進行佈局,省去了不少計算的麻煩;新人更易懂和上手
  2. 更好的性能:這個體如今多處,如瀏覽器寬度改變,瀑布流刷新時候的效率等
  3. 無需知曉尺寸:若是是要絕對定位實現瀑布流,必須知道每一個小模塊的高度以及寬度(不然沒法定位),而基於列表的佈局則無需知道高寬

無聊時候的折騰,有不足與不許確之處歡迎指正。一些實現的具體細節等也是很是歡迎提問交流的。

原創文章,轉載請註明來自 張鑫旭-鑫空間-鑫生活[ http://www.zhangxinxu.com]
相關文章
相關標籤/搜索