先来看下效果图:
瀑布流中的内容可进行自定义,这里的示例图是通过不同背景颜色的展示进行区分,每个瀑布流中添加了自定义图片和文字描述。
实现方式:
1.建立子组件(可单独抽离)写出瀑布流的样式
文件名为waterFall.vue
<template>
<div class="list">
<div
class="item"
v-for="(item, index) in waterList"
:style="{
width: width + 'px',
height: item.height + 'px',
left: item.left + 'px',
top: item.top + 'px',
background: item.background,
}"
>
<img :src="item.image" :alt="item.text" />
<p class="text-box">{{ item.text }}</p>
</div>
</div>
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue';
const props = defineProps({
list: {
type: Array,
default: () => {
return [];
},
},
});
// 图片宽度
const width = 120;
// 图片上下间距
const gap = 20;
// 瀑布流数组
const waterList = ref([]);
// 列高度数组
const heightList = reactive([]);
// 屏幕宽度需要在 mounted 之后拿到
onMounted(() => {
// 计算列数
const column = Math.floor(document.body.clientWidth / width);
// 核心内容就是维护每个图片的 left、top
for (let i = 0; i < props.list.length; i++) {
// 先铺上第一行(i < column 则表示是第一行)
if (i < column) {
props.list[i].top = 0;
props.list[i].left = width * i;
// 塞进瀑布流
waterList.value?.push(props.list[i]);
// 高度数据更新
heightList[i] = props.list[i].height;
}
// 后面的就要一张张塞进去,每次找出最低的列往里塞
else {
// 最低的高度,先默认为第一列高度
let current = heightList[0];
// 最低的列,先默认为第一个
let col = 0;
// 循环每一列进行比较
heightList.forEach((h, i) => {
if (h < current) {
current = h;
col = i;
}
});
console.log('最低的列', col, '高度为', current);
// 由此计算出该图片的 left、top
props.list[i].left = col * width;
props.list[i].top = current + gap;
// 塞进瀑布流
waterList.value.push(props.list[i]);
// 更新列高度数组
heightList[col] = current + gap + props.list[i].height;
}
}
console.log('waterList', waterList.value);
console.log('heightList', heightList);
});
</script>
<style lang="scss" scoped>
.list {
position: relative;
height: 100%;
overflow-y: auto;
width: 100%;
.item {
position: absolute;
.text-box {
font-weight: 500px;
font-size: 18px;
color: #000000;
}
}
}
</style>
2.在父组件中引入使用
父组件中引入使用,其中list为展示的瀑布流数组,class可设置当前瀑布流的一些盒子样式
<water-fall :list="list" class="water-fall" />
3.在父组件中传值实现瀑布流效果
在父组件中设置瀑布流的数据,这里为了方便展示,直接使用的样例数据,实际开发中,可根据接口来进行获取。
其中的height是指瀑布流中每一个的高度,background为背景颜色,image为自定义的图片,text为描述,以上均可根据个人需求进行自定义展示。
const list = [
{
height: 300,
background: 'red',
image: '/images/works-publicity/tradition.png',
text: '平面作品+李宇轩',
},
{
height: 400,
background: 'pink',
text: '美术作品+沈佳宜',
image: '/images/works-publicity/tradition.png',
},
{
height: 500,
background: 'blue',
image: '/images/works-publicity/tradition.png',
text: '平面作品+李宇轩',
},
{
height: 200,
background: 'green',
image: '/images/works-publicity/tradition.png',
text: '平面作品+李宇轩',
},
{
height: 300,
background: 'gray',
image: '/images/works-publicity/tradition.png',
text: '平面作品+李宇轩',
},
{
height: 400,
background: '#CC00FF',
image: '/images/works-publicity/tradition.png',
text: '平面作品+李宇轩',
},
{
height: 200,
background: 'pink',
image: '/images/works-publicity/tradition.png',
text: '平面作品+李宇轩',
},
{
height: 100,
background: '#996666',
image: '/images/works-publicity/tradition.png',
text: '平面作品+李宇轩',
},
{
height: 300,
background: 'gray',
image: '/images/works-publicity/tradition.png',
text: '平面作品+李宇轩',
},
{
height: 400,
background: '#CC00FF',
image: '/images/works-publicity/tradition.png',
text: '平面作品+李宇轩',
},
{
height: 200,
background: 'gray',
image: '/images/works-publicity/tradition.png',
text: '平面作品+李宇轩',
},
{
height: 100,
background: '#996666',
image: '/images/works-publicity/tradition.png',
text: '平面作品+李宇轩',
},
{
height: 300,
background: 'gray',
image: '/images/works-publicity/tradition.png',
text: '平面作品+李宇轩',
},
{
height: 400,
background: '#CC00FF',
image: '/images/works-publicity/tradition.png',
text: '平面作品+李宇轩',
},
{
height: 200,
background: 'gray',
image: '/images/works-publicity/tradition.png',
text: '平面作品+李宇轩',
},
{
height: 100,
background: '#996666',
image: '/images/works-publicity/tradition.png',
text: '平面作品+李宇轩',
},
{
height: 300,
background: 'gray',
image: '/images/works-publicity/tradition.png',
text: '平面作品+李宇轩',
},
{
height: 400,
background: '#CC00FF',
image: '/images/works-publicity/tradition.png',
text: '平面作品+李宇轩',
}
];