Vue 瀑布流布局(封装组件)

一、什么是瀑布流布局

1. 样式展示

如下图所示,每个盒子宽高不同,且能够自适应屏幕变化的布局
在这里插入图片描述

2. 原理分析

利用定位,在最短的一列下面进行排列,如下图所示

图片容器宽度固定,高度根据图片自适应【定宽不定高】,图片一行不能排列时候,换行依次从左往右排列
在这里插入图片描述

来自:https://www.jianshu.com/p/337e277fe098

一、封装 vue 组件

代码来自:https://www.jianshu.com/p/337e277fe098

1. 效果图

可以实现滚动

不加说明文字:
在这里插入图片描述
加上说明文字:
在这里插入图片描述

2. 组件代码:
<template>
	<div class="waterfull">
		<h2>瀑布流布局</h2>
		<div class="v-waterfall-content" id="v-waterfall">
			<div v-for="(img, index) in waterfallList" :key="index" class="v-waterfall-item" :style="{top:img.top+'px',left:img.left+'px',width:waterfallImgWidth+'px',height:img.height}">
				<img :src="img.src" alt="">
				// 说明文字
				<p style="font-size: small;color: #666;margin: 4px;">{{img.title}}</p>
				<p style="font-size: x-small;color: #9e9e9e;margin: 4px;padding-bottom: 6px;">{{img.info}}</p>
			</div>
		</div>
	</div>
</template>

<script>
	export default {
		name: "v-waterfall",
		data() {
			return {
				waterfallList: [],
				imgArr: [
					require('../../assets/waterfullImg/0001.jpg'),
					require('../../assets/waterfullImg/0013.jpg'),
					require('../../assets/waterfullImg/theme01.png'),
					require('../../assets/waterfullImg/0002.jpg'),
					require('../../assets/waterfullImg/theme02.png'),
					require('../../assets/waterfullImg/0014.jpg'),
					require('../../assets/waterfullImg/0002_2.jpg'),
					require('../../assets/waterfullImg/theme06.png'),
					require('../../assets/waterfullImg/0016.jpg')
				],
				// waterfallImgWidth: 100,
				waterfallImgWidth: 200,// 每个盒子的宽度
				// waterfallImgCol: 5,// 瀑布流的列数
				waterfallImgCol: 3,// 瀑布流的列数
				waterfallImgRight: 10,// 每个盒子的右padding
				waterfallImgBottom: 10,// 每个盒子的下padding
				waterfallDeviationHeight: [],
				imgList: []
			}
		},
		created() {
			// 触发入口
			for (let i = 0; i < this.imgArr.length; i++) {
				// this.imgList.push(this.imgArr[Math.round(Math.random() * 8)]);// 图片随机显示
				this.imgList.push(this.imgArr[i]);
			}
		},
		mounted() {
			this.calculationWidth();
		},
		methods: {
			//计算每个图片的宽度或者是列数
			calculationWidth() {
				let domWidth = document.getElementById("v-waterfall").offsetWidth;
				if (!this.waterfallImgWidth && this.waterfallImgCol) {
					this.waterfallImgWidth = (domWidth - this.waterfallImgRight * this.waterfallImgCol) / this.waterfallImgCol;
				} else if (this.waterfallImgWidth && !this.waterfallImgCol) {
					this.waterfallImgCol = Math.floor(domWidth / (this.waterfallImgWidth + this.waterfallImgRight))
				}
				//初始化偏移高度数组
				this.waterfallDeviationHeight = new Array(this.waterfallImgCol);
				for (let i = 0; i < this.waterfallDeviationHeight.length; i++) {
					this.waterfallDeviationHeight[i] = 0;
				}
				this.imgPreloading()
			},
			//图片预加载
			imgPreloading() {
				for (let i = 0; i < this.imgList.length; i++) {
					let aImg = new Image();
					aImg.src = this.imgList[i];
					aImg.onload = aImg.onerror = (e) => {
						let imgData = {};
						imgData.height = this.waterfallImgWidth / aImg.width * aImg.height;
						imgData.src = this.imgList[i];
						imgData.title = '标题';// 说明文字(也可以自己写数组,或者封装json数据,都可以,但是前提是你会相关操作,这里不赘述)
						imgData.info = '详情说明:啦啦啦啦啦';// 说明文字
						this.waterfallList.push(imgData);
						this.rankImg(imgData);
					}
				}
			},
			//瀑布流布局
			rankImg(imgData) {
				let {
					waterfallImgWidth,
					waterfallImgRight,
					waterfallImgBottom,
					waterfallDeviationHeight,
					waterfallImgCol
				} = this;
				let minIndex = this.filterMin();
				imgData.top = waterfallDeviationHeight[minIndex];
				imgData.left = minIndex * (waterfallImgRight + waterfallImgWidth);
				// waterfallDeviationHeight[minIndex] += imgData.height + waterfallImgBottom;// 不加文字的盒子高度
				waterfallDeviationHeight[minIndex] += imgData.height + waterfallImgBottom + 56;// 加了文字的盒子高度,留出文字的地方(这里设置56px)
				console.log(imgData);
			},
			/**
			 * 找到最短的列并返回下标
			 * @returns {number} 下标
			 */
			filterMin() {
				const min = Math.min.apply(null, this.waterfallDeviationHeight);
				return this.waterfallDeviationHeight.indexOf(min);
			}
		}
	}
</script>

<style scoped>
	.waterfull{
		width: 100%;
	}
	.v-waterfall-content {
		/* 主要 */
		width: 100%;height: 400px;position: relative;
		/* 次要:设置滚动条,要求固定高度 */
		overflow-y: auto;
	}

	.v-waterfall-item {
		/* 主要 */
		float: left;position: absolute;
	}

	.v-waterfall-item img {
		/* 主要 */
		/* width: auto;height: auto; */
		width: 90%;height: auto;
		/* 次要 */
		border-radius: 6px;
	}
</style>

  • 14
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 16
    评论
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值