ionic3實戰-隨機佈局瀑布流實現

最近一段時間因爲項目須要接觸到了ionic3,發現真是一個利器啊! 項目中因爲要用到一個瀑布流的特效,找了半天居然沒有找到相關的資源,沒有辦法,只能迎着頭皮上了~ 話很少說,先上圖html

相信看過圖片的同窗都明白什麼意思了吧。對,就是瀑布流! 可是今天咱們的瀑布流可不是通常的瀑布流。讓咱們接着看:

自動排版

咱們的要求是作那種隨機凌亂的感受,因此咱們須要作一種機制,來將圖片選擇最優的一種排列方式來展現到頁面上,也就是保證圖片與相鄰圖片的比例是最合適的而後在實現排列.
複製代碼

angular4

相信這個效果若是在日常的jq插件中彷佛也不難實現,確實,網上也能搜到一些jq的插件。可是咱們的技術棧是angular4呀~
在ng中咱們的DOM操做基本都是放在指令中的,相信用過angularjs1.x的同窗並不陌生了吧~,在angular4中也是同樣。
複製代碼

好了,讓咱們貼代碼~

建立指令

咱們假設你已經在你的ionic中創建好了相關的組件,而且已經擁有的圖片數據,若是沒有相關基礎的同窗建議你們先去看看ionic3 與 angular4的入門。angularjs

這是個人一個組件html的頁面,也許眼尖的同窗已經發現了咱們的指令 [imagr-sort]="item",對的,咱們的指令是須要你當前的圖片的angular數據的。

建立一個指令ts

ionic g directive image-sort 執行創建咱們的指令。 數組

建立完了咱們的自定義指令就是這個樣子,空空如也啊~

編寫咱們的邏輯

1.1接收而且注入一些東西:

看圖! bash

既然咱們在模板中有輸入([[imagr-sort]="item"]);那麼咱們也固然應該在指令中接收到輸入的數據;如截圖中紅色箭頭所示,我將輸入的數據保存了起來->sourceArr; 而後咱們在angular4中若是要獲取到dom宿主的一些屬性了,元素了等等就要用到 ElementRef,Renderer2是angular4中的一個相似渲染器的東西吧,這個具體的我尚未搞懂,你們能夠多看看這塊的資料,我主要是在這個指令中用於更改Dom的一些結構。

關於咱們的imgLength ,我待會再說dom

1.2實際點!圖片是從異步加載過來的!

咱們首先思考這樣一個問題: 咱們的指令是在angular數據渲染的時候就開始執行的,這個是基本你們都懂。 but!咱們的圖片可都是異步加載的呢~,因此天然而然咱們要有一個圖片加載的過程:異步

嗯,相信各位早就想到了---->image.onload,不錯,是它~ 也是時候說下以前的imgLength了,這個變量來記錄記載完成的圖片的數量,用來辨別是否當前圖片都已經加載完畢了,爲咱們後續的動做作依據。

image.onerror,這個相信你們也看明白了吧,這個是圖片加載失敗的一個函數,我在裏面作的操做是將加載失敗的圖片從原始的DOM中,angular的數據剔除。 這裏面就用到了咱們angular的渲染器this.render2(); 相關功能方法你們能夠去源碼裏面看一下,基本上全部經常使用的Dom操做都有實現。 for循環呢是由於咱們的圖片數據是多條的,因此咱們要等待每一張圖片都順利的加載完成。 ps:注意在onerror與onload的函數中使用this要在imgOnlod中使用變量引用let _self = this;angular4

圖片加載完成開始咱們的改造工程

1.3將咱們的適口按照網格劃分

imageStartStort()! 上圖 ionic

你們看1圖紅圈內,我是本身劃分出五個橫向網格標準,便於咱們待會將圖片比例作對比。函數

1.4將咱們的圖片定義網格佔用

咱們建立了一個數組allImageArr=[];用於保存當前處理過的全部圖片的數據。 還記的咱們以前得到的angular的數據吧,咱們經過循環它來將圖片劃分網格佔用。

咱們的循環中都作了些什麼?佈局

1.獲取圖片的寬高,而且求出每一張圖片的比例。

2.將得到的圖片比列與咱們本身定義的網格比例進行區間劃分。

3.按照咱們劃分的網格來計算出佔有網格的圖片的新的寬度,所佔網格數儲存而且記錄保存到咱們的自定義的allImageArr中,而且在原有的angular數據中添加gridding數字那個記錄相應的網格數。

執行this.pictureColumnSort方法;

咱們的圖片已經劃分完成了,接下來,咱們來激情的一刻~

1.5圖片排列,跟據網格派選最合適的鄰居~

pictureColumnSort()! 上圖

這一個過程其實也沒啥好說的,主要就是循環,查看每一個圖片的網格數,將最合適的進行相鄰排序(執行下一步:goExchange函數),最後匹配不上的單獨作一個5分網格戰術出來.

格式能夠是多種: 3+2,1+4,1+1+3,1+3+1,2+3.。。。。。

怎麼高興怎麼來~ 沒啥好說的就是循環篩選,你們看看圖就好。

1.6無序變有序,除了交換應該沒有更好的選擇了吧

goExchange()! 上圖

看看1.5中的代碼,咱們呢是在每次匹配到了合適的圖片以後執行這個函數,由於咱們須要把匹配到的圖片換位置啊! 這個函數中接收到的repeatI與repeatA就是1.5中的雙重循環的索引,這個索引決定了咱們換圖片的位置。

代碼所示的原理就是將匹配到的圖片換到咱們當前圖片的後面,將原來後面的圖片補到換過來圖片的位置,有點繞多是個人比哦打能力很差,哈哈。 沒啥好說的這個函數,就是換位置。

1.7取長補短,完工!

setHeight()!上圖

再次循環(代碼應該還有很多改進的地步,循環用的很多~); 這個地步已經咱們呢的佈局頁面完成了,可是咱們的圖片的尺寸其實是不規則的,不忍直視, 因此咱們在這個函數中將差別抹平,取長補短。

實際上咱們的圖片確定會有一點拉伸,因此咱們也是取了平衡的一箇中間點,來進行適當的拉伸。

這個函數確定其實還能夠作一些適當的限制來精細化圖片的尺寸調整。至此咱們也算是寫完了整個指令邏輯。

完工! ioinc serve

至於中間的調用的過程有一點我要說明:

setTimeout(() => {
        _self.setHeight(angularImageList, ele);
      });

複製代碼

整個調用我也是晚班無奈的狀況下才使用的,若是不加整個調用在setHeight函數中設置的angular,數據會莫名其妙的出現圖片位置更換錯誤,至今誤解,若是大佬們能看到整個有好的解決方法也分享一下。

好了,時間不早了,晚安嘍~

相關文章
相關標籤/搜索