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

CM 朋克發表於2017-12-27

最近一段時間由於專案需要接觸到了ionic3,發現真是一個利器啊! 專案中由於要用到一個瀑布流的特效,找了半天竟然沒有找到相關的資源,沒有辦法,只能迎著頭皮上了~ 話不多說,先上圖

ionic3實戰-隨機佈局瀑布流實現
ionic3實戰-隨機佈局瀑布流實現
ionic3實戰-隨機佈局瀑布流實現
相信看過圖片的同學都明白什麼意思了吧。對,就是瀑布流! 但是今天我們的瀑布流可不是一般的瀑布流。讓我們接著看:

自動排版

我們的要求是做那種隨機凌亂的感覺,所以我們需要做一種機制,來將圖片選擇最優的一種排列方式來展示到頁面上,也就是保證圖片與相鄰圖片的比例是最合適的然後在實現排列.
複製程式碼

angular4

相信這個效果如果在平常的jq外掛中似乎也不難實現,確實,網上也能搜到一些jq的外掛。但是我們的技術棧是angular4呀~
在ng中我們的DOM操作基本都是放在指令中的,相信用過angularjs1.x的同學並不陌生了吧~,在angular4中也是一樣。
複製程式碼

好了,讓我們貼程式碼~

建立指令

我們假設你已經在你的ionic中建立好了相關的元件,並且已經擁有的圖片資料,如果沒有相關基礎的同學建議大家先去看看ionic3 與 angular4的入門。

ionic3實戰-隨機佈局瀑布流實現
這是我的一個元件html的頁面,也許眼尖的同學已經發現了我們的指令 [imagr-sort]="item",對的,我們的指令是需要你當前的圖片的angular資料的。

建立一個指令ts

ionic g directive image-sort 執行建立我們的指令。

ionic3實戰-隨機佈局瀑布流實現
建立完了我們的自定義指令就是這個樣子,空空如也啊~

編寫我們的邏輯

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

看圖!

ionic3實戰-隨機佈局瀑布流實現
既然我們在模板中有輸入([[imagr-sort]="item"]);那麼我們也當然應該在指令中接收到輸入的資料;如截圖中紅色箭頭所示,我將輸入的資料儲存了起來->sourceArr; 然後我們在angular4中如果要獲取到dom宿主的一些屬性了,元素了等等就要用到 ElementRef,Renderer2是angular4中的一個類似渲染器的東西吧,這個具體的我還沒有搞懂,大家可以多看看這塊的資料,我主要是在這個指令中用於更改Dom的一些結構。

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

1.2實際點!圖片是從非同步載入過來的!

我們首先思考這樣一個問題: 我們的指令是在angular資料渲染的時候就開始執行的,這個是基本大家都懂。 but!我們的圖片可都是非同步載入的呢~,所以自然而然我們要有一個圖片載入的過程:

ionic3實戰-隨機佈局瀑布流實現
嗯,相信各位早就想到了---->image.onload,不錯,是它~ 也是時候說下之前的imgLength了,這個變數來記錄記載完成的圖片的數量,用來辨別是否當前圖片都已經載入完畢了,為我們後續的動作做依據。

image.onerror,這個相信大家也看明白了吧,這個是圖片載入失敗的一個函式,我在裡面做的操作是將載入失敗的圖片從原始的DOM中,angular的資料剔除。 這裡面就用到了我們angular的渲染器this.render2(); 相關功能方法大家可以去原始碼裡面看一下,基本上所有常用的Dom操作都有實現。 for迴圈呢是因為我們的圖片資料是多條的,所以我們要等待每一張圖片都順利的載入完成。 ps:注意在onerror與onload的函式中使用this要在imgOnlod中使用變數引用let _self = this;

圖片載入完成開始我們的改造工程

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

imageStartStort()! 上圖

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

大家看1圖紅圈內,我是自己劃分出五個橫向網格標準,便於我們待會將圖片比例做對比。

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

ionic3實戰-隨機佈局瀑布流實現
ionic3實戰-隨機佈局瀑布流實現
我們建立了一個陣列allImageArr=[];用於儲存當前處理過的所有圖片的資料。 還記的我們之前獲得的angular的資料吧,我們通過迴圈它來將圖片劃分網格佔用。

我們的迴圈中都做了些什麼?

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

2.將獲得的圖片比列與我們自己定義的網格比例進行區間劃分。

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

執行this.pictureColumnSort方法;

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

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

pictureColumnSort()! 上圖

ionic3實戰-隨機佈局瀑布流實現
這一個過程其實也沒啥好說的,主要就是迴圈,檢視每個圖片的網格數,將最合適的進行相鄰排序(執行下一步:goExchange函式),最後匹配不上的單獨做一個5分網格戰術出來.

格式可以是多種: 3+2,1+4,1+1+3,1+3+1,2+3.。。。。。

怎麼高興怎麼來~ 沒啥好說的就是迴圈篩選,大家看看圖就好。

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

goExchange()! 上圖

ionic3實戰-隨機佈局瀑布流實現
看看1.5中的程式碼,我們呢是在每次匹配到了合適的圖片之後執行這個函式,因為我們需要把匹配到的圖片換位置啊! 這個函式中接收到的repeatI與repeatA就是1.5中的雙重迴圈的索引,這個索引決定了我們換圖片的位置。

程式碼所示的原理就是將匹配到的圖片換到我們當前圖片的後面,將原來後面的圖片補到換過來圖片的位置,有點繞可能是我的比哦打能力不好,哈哈。 沒啥好說的這個函式,就是換位置。

1.7取長補短,完工!

setHeight()!上圖

ionic3實戰-隨機佈局瀑布流實現
再次迴圈(程式碼應該還有不少改進的地步,迴圈用的不少~); 這個地步已經我們呢的佈局頁面完成了,但是我們的圖片的尺寸實際上是不規則的,不忍直視, 所以我們在這個函式中將差異抹平,取長補短。

實際上我們的圖片肯定會有一點拉伸,所以我們也是取了平衡的一箇中間點,來進行適當的拉伸。

這個函式肯定其實還可以做一些適當的限制來精細化圖片的尺寸調整。至此我們也算是寫完了整個指令邏輯。

完工! ioinc serve

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

至於中間的呼叫的過程有一點我要說明:

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

複製程式碼

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

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

相關文章