将以下代码写成一个组件即可使用
<div class="waterfall" ref="waterfall">
<img class="waterfall-image" :src="item" alt="" v-for="(item, index) in imageArr" @load="setPosition">
</div>
<script setup lang="ts">
import { ref, onMounted } from "vue"
// ********将下面的数组换成请求的接口数据既可,现在是测试图片地址
// 注意!!!!如果图片来源于请求使用watch监听imageArr不然会显示不出来
const imageArr = ref<string[]>([img1, img2, img3, img4, img5,img1, img2, img3, img4, img5,img1, img2, img3, img4, img5])
// 瀑布流父容器
const waterfall = ref<HTMLDivElement | null>(null)
// 图片的宽度
const imageWidth: number = 277
// 图片的列间距
const imageColMargin: number = 20
// 父容器的宽度
let parentWidth: number = 0
// 有几列图片
const imageCol: number[] = [];
// 开始布局
onMounted(() => {
getImageCol();
})
// 父容器能容纳多少列
const getImageCol = (): void => {
if (!waterfall.value) return;
parentWidth = waterfall.value.getBoundingClientRect().width
// 添加图片的列数高度
for (let i = 0; i < Math.floor(parentWidth / imageWidth); i++) {
imageCol.push(0)
}
}
const setPosition = (e: Event): void => {
const image = e.target as HTMLImageElement
// 假设最小值为第0个
let minIndex = 0;
// 遍历数组并更新最小值及其索引
for (let i = 1; i < imageCol.length; i++) {
if (imageCol[i] < imageCol[minIndex]) {
minIndex = i;
}
}
// 设置图片的位置
image.style.top = imageCol[minIndex] + 'px'
// 他的left就是 图片的固定宽度加剩余宽度
image.style.left = minIndex * ((parentWidth % imageWidth / (imageCol.length-1)) + imageWidth) + 'px'
imageCol[minIndex] += image.clientHeight + imageColMargin
// 最后设置父容器的坍塌高度
if(!waterfall.value) return;
waterfall.value.style.height = Math.max(...imageCol) + 'px'
}
/// 瀑布流布局功能结束
</script>
注意waterfall-image的宽度要和js代码中的imageWidth一样
// 使用scss或less
.waterfall {
position: relative;
.waterfall-image {
position: absolute;
width: 277px;
}
}