瀑布流是一種很常見的網頁佈局,視覺表現為參差不齊的多欄佈局,是一種時下很流行的佈局形式,最近在寫小程序恰好也碰到了,想了幾種不同的實作方法,接下來就來一起看看具體的實作方法(所用的方法中用的例子都是兩欄的版面)。
等高的瀑布流顧名思義就是瀑布流裡的單一盒子的高度都是一樣的,這種形式的瀑布流實現起來也比較簡單,因為不涉及到盒子高度的計算,舉個例子:
<view> <view></view> </view>
Page({ data: { list: [] }, onLoad () { let images = [] for (let i = 0; i <pre class="brush:php;toolbar:false">.fall { display: flex; flex-wrap: wrap; background-color: #f7f7f7; } .fall-item { width: 330rpx; height: 330rpx; margin-top: 30rpx; margin-left: 30rpx; background-color: aquamarine; }
為了方便,例子中的盒子內容並沒有使用圖片,而是使用了色塊代替,等高瀑布流的實現可以直接通過flex佈局實現,如例子所示,直接用flex佈局,允許換行,設置好瀑布流里中每一個盒子的寬高,就能實現簡單的實現兩欄瀑布流佈局
不等高瀑布流是更為常見的形式,不等高瀑布流涉及到列高的計算,由於每個盒子的高度不一樣,因此需要每一列的列高都要記錄、比較,將下一個盒子插入高度矮的一列,接下來就來看看不等高瀑布流的實現方式
#一般瀑布流裡展示的都是圖片,這種情況指的是服務端會返給前端要展示的圖片的寬高,這種情況下相對也比較簡單,因為服務端會返回圖片的寬高,前端只需要計算一下列高,將下一張圖片插入矮的那裡一列就可以,舉個例子:
<view> <view> <view></view> </view> </view>
.fall { display: flex; background-color: #f7f7f7; } .fall-column { display: flex; flex-direction: column; margin-left: 30rpx; } .fall-column-item { width: 330rpx; margin-top: 30rpx; background-color: aquamarine; }
Page({ data: { images: [{ width: 360, height: 540 }, { width: 480, height: 540 }, { width: 540, height: 720 }, { width: 720, height: 960 }, { width: 540, height: 960 }, { width: 360, height: 720 }, { width: 360, height: 960 }, { width: 540, height: 540 }, { width: 540, height: 1440 }, { width: 960, height: 1440 }], heightArr: [], list: [], col: 2 }, onLoad () { this.initData(2) }, initData (col) { let images = [] let scale = 2 // 模拟图片宽高 for (let i = 0; i <p>上例中為了方便也是用色塊模擬了圖片,在js中模擬了10張圖片的寬高,每次從中隨機取10張圖片,定義了兩列,每次計算一下每列的高度,將圖片插入矮的那一列,然後將記錄用高度數組,將圖片的高度累加,實現起來也很簡單</p><h3>未知盒子高度</h3><p>未知盒子高度的情況下,我們要怎麼做呢? </p><h4>wx.getImageInfo</h4><p>第一種辦法就是透過wx.getImageInfo可以取得到圖片寬高信息,舉個例子:</p><pre class="brush:php;toolbar:false"><view> <view> <view> <image></image> </view> </view> </view>
.fall { display: flex; background-color: #f7f7f7; } .fall-column { display: flex; flex-direction: column; margin-left: 30rpx; } .fall-column-item { margin-top: 30rpx; line-height: 0; } .fall-column-item-img { width: 330rpx; }
import api from '../../api/index' Page({ data: { list: [], heightArr: [] }, async onLoad () { let {results} = await api.fetchImages() let col = 2 for (let i in results) { results[i].cover = results[i].imageUrl // 获取图片信息 let info = await this.loadImage(results[i].cover) results[i].height = 165 / info.width * info.height if (i { wx.getImageInfo({ src: cover, success: (res) => { resolve(res) } }) }) } })
當服務端沒有回傳圖片的寬高時,可以直接透過wx.getImageInfo()獲取到圖片的信息,這裡為了不打亂服務返回時的圖片順序,特意將這個單獨用Promise封了一層,就是為了圖片加載完一張再獲取下一張,但是當圖片比較大的時候就會導致載入的時間會很長,會有長時間的白屏:
這是因為wx.getImageInfo()獲取圖片資訊的時候會先將圖片下載下來,然後才能獲取圖片信息,這就導致時間會比較長,但是如果不需要圖片加載順序時可以考慮直接並行加載,不等上一張圖片加載完就加載下一張,這樣就能更快的展現
既然圖片載入獲取資訊時間比較長,那考慮是否可以加上一個預設的圖片,這樣用戶才能在第一時間看到有內容展示,圖片資訊拿到後再將圖片顯示出來,舉個例子:
<view> <view> <view> <image></image> </view> </view> </view>
.fall { display: flex; background-color: #f7f7f7; } .fall-column { display: flex; flex-direction: column; margin-left: 30rpx; } .fall-column-item { position: relative; margin-top: 30rpx; line-height: 0; background-color: #ccc; } .fall-column-item::after { content: '加载中'; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); display: inline-block; color: #666; } .fall-column-item-img { position: relative; width: 330rpx; z-index: 1; }
import api from '../../api/index' Page({ data: { list: [], heightArr: [] }, async onLoad () { let {results} = await api.fetchImages() let col = 2 for (let i = 0; i { wx.getImageInfo({ src: cover, success: (res) => { resolve(res) } }) }) } })
這個例子中就在圖片沒有加載完之前給了一個默認的加載中的顯示,當然這只是一個簡單的例子,只能提供簡單的優化思路,實際中的加載過渡動畫一定會設計得更細膩
一般小程序中用到的圖片都是儲存在雲端伺服器上的,且雲端伺服器一般都會提供在圖片請求地址上帶參數獲取圖片信息,以阿里雲為例,可以在圖片連結上拼接?x-oss-process=image /info,就能獲取到圖片信息,舉個例子:
<view> <view> <view> <image></image> </view> </view> </view>
.fall { display: flex; background-color: #f7f7f7; } .fall-column { display: flex; flex-direction: column; margin-left: 30rpx; } .fall-column-item { position: relative; margin-top: 30rpx; line-height: 0; background-color: #ccc; } .fall-column-item::after { content: '加载中'; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); display: inline-block; color: #666; } .fall-column-item-img { position: relative; width: 330rpx; z-index: 1; }
let fetchPicInfo = async (url) => { let [err, result] = await to(testFly.get(`${url}?x-oss-process=image/info`)) if (err) throw err return result.data }
import api from '../../api/index' Page({ data: { list: [], heightArr: [] }, async onLoad () { let {results} = await api.fetchImages() let col = 2 for (let i = 0; i <p>透過這個方法可以大大減少圖片加載的時間,不需要將圖片下載到本地在獲取圖片信息,而是直接向服務器請求圖片訊息,再加上每次請求只會返回圖片基本資訊就幾個字段,因此請求時間也非常短,如圖:<br><img src="https://img.php.cn/upload/image/137/787/730/1592535565112393.png" title="1592535565112393.png" alt="小程式中的瀑布流"></p><p>這樣用戶能更快看到圖片顯示,同時也加上了圖片載入時的過渡效果,這樣體驗效果會更好</p><h2>總結</h2><p>這篇文章把最近在寫小程式時遇到的瀑布流做了一個比較詳細的總結,不同的情況下選擇不同的加載方案,體驗效果最好的當然還是服務端直接返回圖片信息,這樣能節省很多獲取圖片信息要花的時間,這樣用戶體驗更優,希望能對各位在寫小程式瀑布流能有所幫助。 <br><br>如果有錯誤或不嚴謹的地方,歡迎批評指正,如果喜歡,歡迎點讚</p><p>推薦教學:《<a href="https://www.php.cn/weixin-marketing.html" target="_blank">微信小程式</a>》</p>
以上是小程式中的瀑布流的詳細內容。更多資訊請關注PHP中文網其他相關文章!