Appearance
瀑布流
一、网格布局 display: grid
关键代码:
vue
<view class="item" :key="index" :style="'grid-row: auto / span '+ (arrRowList[index] || 0) +';'">
</view>
vue
//获取元素高度
let height = ret.height;
//计算span
span = Math.floor(height / 5) + 2;
关键样式:
css
.list{
display: grid;
/*指定两列,自动宽度*/
grid-template-columns: repeat(2, 1fr);
/*横向间隔*/
grid-column-gap: 24rpx;
grid-row-gap: 0;
/*是否自动补齐空白*/
grid-auto-flow: row dense;
/*base高度,grid-row基于此运算*/
grid-auto-rows: 5px;
}
完整代码:
vue
<template>
<view class="flow-wrap">
<List ref="list" :openLoad="!bAllLoaded" @refresh="loadTop" @load="loadBottom">
<view class="list">
<template v-for="(item,index) in arrList">
<view class="item" :key="index"
:style="'grid-row: auto / span '+ (arrRowList[index] || 0) +';'">
<image :src="item.url" class="img" mode="widthFix"></image>
<view class="text">{{ item.text }}({{index + 1}})</view>
</view>
</template>
</view>
</List>
<view id="count" class="count-box">
<view class="item">
<image :src="objItem.url" class="img" mode="widthFix"></image>
<view class="text">{{ objItem.text }}</view>
</view>
</view>
</view>
</template>
<script>
import List from '/src/components/list/list';
export default {
name: "flow",
components: {
List
},
data() {
return {
bAllLoaded: false,
objItem: {},//用于计算高度的数据
arrList: [],
arrRowList: []
}
},
methods: {
upDate() {
uni.showLoading({
title: '加载中',
mask: true
})
this.arrRowList = [];
this.arrList = [];
this.getList().then(() => {
uni.hideLoading()
})
},
itemStyle(index) {
const item = this.imageList[index]
const itemWidth = (this.screenWidth - (this.columnNum - 1) * this.columnGap) / this.columnNum
const itemHeight = item.height * (itemWidth / item.width)
const colIndex = index % this.columnNum
const rowIndex = Math.floor(index / this.columnNum)
const marginTop = rowIndex === 0 ? 0 : this.columnGap
const marginLeft = colIndex === 0 ? 0 : this.columnGap
return {
width: `${itemWidth}px`,
height: `${itemHeight}px`,
marginTop: `${marginTop}px`,
marginLeft: `${marginLeft}px`,
}
},
getList() {
return new Promise((resolve, reject) => {
// 模拟接口返回
setTimeout(() => {
let arr = [{
url: 'https://pro-mixed-test.babycdn.com/base/digi/uploads/digi_demo/46/43/1679624643_5266.jpg',
text: '文本'
}, {
url: require('@/static/image/flow/flow2.jpg'),
text: '文本'
}, {
url: require('@/static/image/flow/flow2.jpg'),
text: '文本'
}, {
url: require('@/static/image/flow/flow3.jpg'),
text: '文本'
}, {
url: require('@/static/image/flow/flow.jpg'),
text: '文本'
}, {
url: require('@/static/image/flow/flow2.jpg'),
text: '文本'
}, {
url: 'https://pro-mixed-test.babycdn.com/base/digi/uploads/digi_demo/47/01/1679624701_7772.jpg',
text: '文本'
}, {
url: require('@/static/image/flow/flow.jpg'),
text: '文本'
},]
this.count(arr).then(() => {
resolve()
})
}, 1000)
})
},
count(arr) {
return new Promise(async (resolve, reject) => {
for (let i = 0; i < arr.length; i++) {
this.objItem = arr[i];
let span = await this.getItemHeight()
this.arrRowList.push(span)
if (i == arr.length - 1) {
this.arrList.push(...arr);
resolve()
}
}
})
},
getItemHeight() {
return new Promise((resolve, reject) => {
this.$nextTick(() => {
setTimeout(() => {
let query = uni.createSelectorQuery().in(this)
query.select('#count').boundingClientRect(ret => {
let span = 0;
let height = ret.height;
span = Math.floor(height / 5) + 2;
resolve(span)
}).exec();
}, 500)
})
})
},
loadTop() {
this.arrRowList = [];
this.arrList = [];
this.getList().then(() => {
this.$refs.list.endUpate()
})
},
loadBottom() {
this.getList().then(() => {
this.$refs.list.endUpate()
})
}
}
}
</script>
<style lang="scss" scoped>
.flow-wrap {
width: 100%;
height: 100%;
.list {
width: 100%;
padding: 0 32rpx;
box-sizing: border-box;
/*column-gap: 24rpx;*/
/*column-count: 2;*/
display: grid;
/*指定两列,自动宽度*/
grid-template-columns: repeat(2, 1fr);
/*横向间隔*/
grid-column-gap: 24rpx;
grid-row-gap: 0;
/*是否自动补齐空白*/
grid-auto-flow: row dense;
/*base高度,grid-row基于此运算*/
grid-auto-rows: 5px;
.item {
width: 100%;
height: fit-content;
overflow: hidden;
box-sizing: border-box;
padding: 10rpx;
border: 1px solid #e2e2e2;
border-radius: 12rpx;
.img {
width: 100%;
display: block;
border-radius: 12rpx;
}
.text {
font-size: 28rpx;
line-height: 40rpx;
}
}
}
.count-box {
width: 90%;
height: fit-content;
position: fixed;
top: 0;
left: 0;
z-index: -999;
opacity: 0;
.item {
width: 50%;
height: fit-content;
overflow: hidden;
box-sizing: border-box;
padding: 10rpx;
border: 1px solid #e2e2e2;
border-radius: 12rpx;
.img {
width: 100%;
display: block;
border-radius: 12rpx;
}
.text {
font-size: 28rpx;
line-height: 40rpx;
}
}
}
}
</style>