這篇文章將為大家詳細講解有關小程序中的瀑布流是什么意思,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
瀑布流是一種很常見的網頁布局,視覺表現為參差不齊的多欄布局,是一種時下很流行的布局形式,最近在寫小程序恰好也碰到了,想了幾種不同的實現方法,接下來就來一起看看具體的實現方法(所用的方法中用的例子都是兩欄的布局)。
等高的瀑布流顧名思義就是瀑布流里的單個盒子的高度都是一樣的,這種形式的瀑布流實現起來也比較簡單,因為不涉及到盒子高度的計算,舉個例子:
<view class="fall">
<view wx:for="{{list}}" class="fall-item"></view>
</view>Page({
data: {
list: []
},
onLoad () {
let images = []
for (let i = 0; i < 10; i++) {
images.push({
url: 'test'
})
}
this.setData({
list: images
})
}
}).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 class="fall">
<view wx:for="{{list}}" wx:for-index="idx" wx:for-item="column" class="fall-column">
<view class="fall-column-item" wx:for="{{column}}" wx:for-index="i" wx:for-item="item" style="height: {{item.showHeight}}rpx"></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 < 10; i++) {
let image = this.data.images[Math.floor(Math.random() * 10)]
images.push(image)
}
for (let i in images) {
let height = 165 / images[i].width * images[i].height * scale
images[i].showHeight = height
// 第一行的兩個盒子
if (i < col) {
this.data.list.push([images[i]])
this.data.heightArr.push(height)
} else {
// 選出高度較矮的一列的索引
let minHeight = Math.min.apply(null, this.data.heightArr)
let minHeightIndex = this.data.heightArr.indexOf(minHeight)
this.data.list[minHeightIndex].push(images[i])
this.data.heightArr[minHeightIndex] += height
}
}
this.setData({
list: this.data.list
})
},
onReachBottom () {
this.initData(0)
}
})上例中為了方便也是用色塊模擬了圖片,在js中模擬了10張圖片的寬高,每次從中隨機取10張圖片,定義了兩列,每次計算一下每列的高度,將圖片插入矮的那一列,然后將記錄用高度數組,將圖片的高度累加,實現起來也很簡單
未知盒子高度的情況下,我們要怎么做呢?
第一種辦法就是通過wx.getImageInfo可以獲取到圖片寬高信息,舉個例子:
<view class="fall">
<view class="fall-column" wx:for="{{list}}" wx:for-index="idx" wx:for-item="column" wx:key="{{idx}}">
<view class="fall-column-item" wx:for="{{column}}" wx:for-index="i" wx:key="{{i}}" wx:for-item="item">
<image class="fall-column-item-img" src="{{item.cover}}" mode="widthFix"/>
</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 < col) {
this.data.list.push([results[i]])
this.data.heightArr.push(results[i].height)
} else {
let minHeight = Math.min.apply(null, this.data.heightArr)
let minHeightIndex = this.data.heightArr.indexOf(minHeight)
this.data.list[minHeightIndex].push(results[i])
this.data.heightArr[minHeightIndex] += results[i].height
}
}
this.setData({
list: this.data.list
})
},
loadImage (cover) {
return new Promise(resolve => {
wx.getImageInfo({
src: cover,
success: (res) => {
resolve(res)
}
})
})
}
})當服務端沒有返回圖片的寬高時,可以直接通過wx.getImageInfo()獲取到圖片的信息,這里為了不打亂服務返回時的圖片順序,特意將這個單獨用Promise封了一層,就是為了圖片加載完一張再獲取下一張,但是當圖片比較大的時候就會導致加載的時間會很長,會有長時間的白屏:
這是因為wx.getImageInfo()獲取圖片信息的時候會先將圖片下載下來,然后才能獲取圖片信息,這就導致時間會比較長,但是如果不需要圖片加載順序時可以考慮直接并行加載,不等上一張圖片加載完就加載下一張,這樣就能更快的展現
既然圖片加載獲取信息時間比較長,那考慮是否可以加上一個默認的圖片,這樣用戶能在第一時間看到有內容展示,圖片信息拿到后再將圖片顯示出來,舉個例子:
<view class="fall">
<view class="fall-column" wx:for="{{list}}" wx:for-index="idx" wx:for-item="column" wx:key="{{idx}}">
<view class="fall-column-item" wx:for="{{column}}" wx:for-index="i" wx:for-item="item" wx:key="{{i}}">
<image class="fall-column-item-img" src="{{item.cover}}" mode="widthFix"/>
</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 < col; i++) {
this.data.list[i] = new Array(results.length / 2)
}
this.setData({
list: this.data.list
})
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 < col) {
this.data.list[i][0] = results[i]
this.data.heightArr.push(results[i].height)
} else {
let minHeight = Math.min.apply(null, this.data.heightArr)
let minHeightIndex = this.data.heightArr.indexOf(minHeight)
let index = this.data.list[minHeightIndex].filter(Boolean).length
this.data.list[minHeightIndex][index] = results[i]
this.data.heightArr[minHeightIndex] += results[i].height
}
}
for (let i = 0; i < col; i++) {
this.data.list[i] = this.data.list[i].filter(Boolean)
}
this.setData({
list: this.data.list
})
},
loadImage (cover) {
return new Promise(resolve => {
wx.getImageInfo({
src: cover,
success: (res) => {
resolve(res)
}
})
})
}
})這個例子中就在圖片沒有加載完之前給了一個默認的加載中的顯示,當然這只是一個簡單的例子,只能提供簡單的優化思路,實際中的加載過渡動畫一定會設計得更細膩
一般小程序中用到的圖片都是存儲在云服務器上的,且云服務器一般都會提供在圖片請求地址上帶參數獲取圖片信息,以阿里云為例,可以在圖片鏈接上拼接?x-oss-process=image/info,就能獲取到圖片信息,舉個例子:
<view class="fall">
<view class="fall-column" wx:for="{{list}}" wx:for-index="idx" wx:for-item="column" wx:key="{{idx}}">
<view class="fall-column-item" wx:for="{{column}}" wx:for-index="i" wx:for-item="item" wx:key="{{i}}">
<image class="fall-column-item-img" src="{{item.cover}}" mode="widthFix"/>
</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 < col; i++) {
this.data.list[i] = new Array(results.length / 2)
}
this.setData({
list: this.data.list
})
for (let i in results) {
results[i].cover = results[i].imageUrl
let info = await api.fetchPicInfo(results[i].cover)
results[i].height = 165 / info.ImageWidth.value * info.ImageHeight.value
if (i < col) {
this.data.list[i][0] = results[i]
this.data.heightArr.push(results[i].height)
} else {
let minHeight = Math.min.apply(null, this.data.heightArr)
let minHeightIndex = this.data.heightArr.indexOf(minHeight)
let index = this.data.list[minHeightIndex].filter(Boolean).length
this.data.list[minHeightIndex][index] = results[i]
this.data.heightArr[minHeightIndex] += results[i].height
}
}
for (let i = 0; i < col; i++) {
this.data.list[i] = this.data.list[i].filter(Boolean)
}
this.setData({
list: this.data.list
})
}
})通過這個方法可以大大減少圖片加載的時間,不需要將圖片下載到本地在獲取圖片信息,而是直接向服務器請求圖片信息,再加上每次請求只會返回圖片基本信息就幾個字段,因此請求時間也非常短,如圖:
這樣用戶能更快看到圖片顯示,同時也加上了圖片加載時的過渡效果,這樣體驗效果會更好
關于“小程序中的瀑布流是什么意思”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。