以下以微信小程序为例
<template>
<view class="box">
<view
v-for="(item, index) in list"
:key="index"
:class="`card card${index + 1}`"
:style="'position:absolute;top:' + item.top + 'px;left:' + item.left + 'px'"
>{{ item }}</view
>
</view>
</template>
<script lang="ts">
import { reactive, toRefs } from 'vue'
import Taro, { nextTick, useDidShow, useReachBottom } from '@tarojs/taro'
export default {
setup() {
const _data = reactive({
list: [
{
a: '1111',
b: '2222',
},
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
],
screenWidth: 375,
})
let _columnHeightArr = []
let result = []
useDidShow(() => {
nextTick(() => {
waterFall('.card', { gap: 10 }).then((arr) => {
if (!arr.length) return
_data.list = _data.list.map((item, index) => ({ ...item, ...arr[index] }))
})
})
})
useReachBottom(() => {
const oldListLen = _data.list.length
_data.list = _data.list.concat(['10', '11', '12'])
setTimeout(() => {
waterFall('.card', { gap: 10, startIndex: oldListLen }).then((arr) => {
if (!arr.length) return
_data.list = _data.list.map((item, index) => ({ ...item, ...arr[index] }))
})
}, 200)
})
const getAllRect = (selector) => {
return new Promise((resolve) => {
Taro.createSelectorQuery()
.selectAll(selector)
.boundingClientRect()
.exec((rect) => {
if (rect === void 0) {
rect = []
}
return resolve(rect[0])
})
})
}
const waterFall = async (selector, options = {}) => {
let items = await getAllRect(selector)
if (items.length <= 0) return []
let { startIndex = 0, gap = 15, column = 2, padding = 0, width = 375, firstColumnToTop = 0 } = options
let itemWidth = items[0].width
if (gap === 'auto') {
gap = (width - itemWidth * column) / (column - 1)
}
for (let i = startIndex, len = items.length; i < len; i++) {
if (i < column) {
let top = firstColumnToTop
let left = (itemWidth + gap) * i + padding
if (i === 0 || i === len - 1) {
left = padding
}
_columnHeightArr.push(items[i].height + top)
result.push({
top,
left,
height: items[i].height,
})
} else {
let minHeight = Math.min(..._columnHeightArr)
let minIndex = _columnHeightArr.findIndex((item) => item === minHeight)
result.push({
top: _columnHeightArr[minIndex] + gap,
left: result[minIndex].left,
height: items[i].height,
})
_columnHeightArr[minIndex] = _columnHeightArr[minIndex] + items[i].height + gap
}
}
return result
}
return {
...toRefs(_data),
}
},
}
</script>
<style lang="scss">
.box {
display: flex;
flex-wrap: wrap;
padding: 0 10px;
}
.card {
width: 150px;
height: 150px;
background-color: rebeccapurple;
&1 {
width: 150px;
height: 250px;
background-color: gold;
}
&2 {
width: 150px;
height: 240px;
background-color: darkblue;
}
&3 {
width: 150px;
height: 230px;
background-color: #4fc08d;
}
&4 {
width: 150px;
height: 220px;
background-color: #7d8d8a;
}
&5 {
width: 150px;
height: 195px;
background-color: chocolate;
}
&6 {
width: 150px;
height: 170px;
background-color: aqua;
}
&7 {
width: 150px;
height: 250px;
background-color: #1f2136;
}
&8 {
width: 150px;
height: 190px;
background-color: wheat;
}
&9 {
width: 150px;
height: 210px;
background-color: #00a4aa;
}
}
</style>