先来看下效果图:
瀑布流中的内容可进行自定义,这里的示例图是通过不同背景颜色的展示进行区分,每个瀑布流中添加了自定义图片和文字描述。
实现方式:
1.建立子组件(可单独抽离)写出瀑布流的样式
文件名为waterFall.vue
<template><div class="list"><divclass="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、topfor (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、topprops.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: '平面作品+李宇轩',}
];