效果图:

uniapp 获取图片在android上的本地路径 uniapp图片加载_瀑布流

说明:

                函数说明:传入一个数组,循环获取图片高度,会根据把原数组拆分成两个数组,放在两列,
                计算单列累计高度,对比高度值的大小,实现瀑布流的布局,
                由于获取图片高度需要一定的时间,所以使用async await 阻塞for 循环的进程,
                每获取到一个图片的高度就赋值渲染到页面上,实现加载出一个图片就先渲染上去,达成图片懒加载的效果
                
                参数说明:
                必填:
                    arr:数组,里面有对象,对比对象里面的图片高度,返回两个数组
                    attributeName:要根据数组里对象指定属性名称(图片的 Key)
                非必填:
                    otherHeight:瀑布流的盒子其它组成部分的高度,例如点赞那行,因为瀑布流不单单是图片组成
                    minHeight: 图片最小高度,如果没有图片,也会使用最小高度,相当于默认高度
                    maxHeight:图片最大高度,超出高度就按照 maxHeight 进入当前列累计高度

代码:

<template>
	<div class="page">
		<scroll-view style="height: 800px;" scroll-y="true" class="scroll-Y" @scrolltolower="loadMoreImages">
			<view class="main">
				<div class="view Left">
					<div class="content" v-for="(item, index) in firstList" :key="index">
						<div class="img-content">
							<div class="modle_mask" v-if="item.audit_status == 8">
								{{ item.audit_status == 8 ? "审核中":'' }}
							</div>
							<div class="modle_mask" @click="openfail(item)" v-if="item.audit_status == 2">
								{{ item.audit_status==2 ? "审核未通过" : "" }}
							</div>
							<image v-if="item.faceimg" :src="item.faceimg" class="image" mode="widthFix" :data-index="index" data-type="1"
							 @click="goDetails(item)" />
							<img v-if="item.identity_type=='identity_type_admin'" class="approveImg" mode="heightFix" :src="approve" />
						</div>
						<div class="text" v-if="type" @click="goDetails(item)">{{ item.title }}</div>
						<div class="price" v-if="type">
							<div class="users">
								<img class="avatarUrl" :src="item.head_img" />
								<div class="nickName">{{ item.nick_name }}</div>
							</div>
							<div class="give" @click="giveLike(item,index,'firstList')">
								<img class="giveXin" :src="item.use_fabulous?aixin2:aixin1" />
								<div class="giveNum">{{ item.fabulous_num }}</div>
							</div>
						</div>
					</div>
				</div>
				<div class="view Right">
					<div class="content" v-for="(item, index) in secondList" :key="index">
						<div class="img-content">
							<div class="modle_mask" v-if="item.audit_status == 8">
								{{ item.audit_status == 8 ? "审核中":'' }}
							</div>
							<div class="modle_mask" @click="openfail(item)" v-if="item.audit_status == 2">
								{{ item.audit_status == 2 ? "审核未通过" : "" }}
							</div>
							<image v-if="item.faceimg" :src="item.faceimg" class="image" mode="widthFix" :data-index="index" data-type="2"
							 @click="goDetails(item)" />
							<img v-if="item.identity_type=='identity_type_admin'" class="approveImg" :src="approve" />
						</div>
						<div v-if="type" class="text" @click="goDetails(item)">{{ item.title }}</div>
						<div v-if="type" class="price">
							<div class="users">
								<img class="avatarUrl" :src="item.head_img" />
								<div class="nickName">{{ item.nick_name }}</div>
							</div>
							<div class="give" @click="giveLike(item,index,'secondList')">
								<img class="giveXin" :src="item.use_fabulous?aixin2:aixin1" />
								<div class="giveNum">{{ item.fabulous_num }}</div>
							</div>
						</div>
					</div>
				</div>
			</view>

		</scroll-view>
		<view class="modal_mask" v-if="isTips">
			<view class="modaltips">
				<view class="modalPages">
					<image :src="failImage" class="coverImage"></image>
					<view class="modelText1">很遗憾</view>
					<view class="modelText1" style="margin-bottom: 70rpx">您的审核未通过</view>
					<view class="modelText2">审核未通过原因:</view>
					<view class="modelText2">{{ failText }}</view>
					<view class="back" @click="close">返回</view>
				</view>
			</view>
		</view>
	</div>
</template>

<script>
	export default {
		props: {
			params: Object, //forumLists 接口的其它参数
			type: String, //好物种草我的嗮图传 type 嗮图 userForumLists,赞过 userFabulousLists
			url: String // 判断是哪个社区模块调用的,imgCommunity 好物种草
		},

		data() {
			return {
				aixin1: this.$config.nhsImagesUrl + "community/aixin1xxxx.png",
				aixin2: this.$config.nhsImagesUrl + "community/aixin2ssss.png",
				failImage: this.$config.nhsImagesUrl + "community/fail.png",
				approve: this.$config.nhsImagesUrl + "community/approve.png",
				request_url: "",
				showImg: false,
				failText: "",
				dataList: [], // 数据源
				firstList: [], // 第一列数组
				secondList: [], // 第二列数组
				windowWidth: 0, // 页面视图宽度
				windowHeight: 0, // 视图高度
				imgMargin: 0, // 图片边距: 单位px
				imgWidth: 0, // 图片宽度: 单位px
				topArr: [0, 0], // 存储每列的累积top
				pageSize: 8,
				last: false,
				page: 1,
				like: true,
				isTips: false,
				i: 0
			};
		},
		created() {
			this.init();
			this.getGoodthingList();
			console.log('created-type', this.type)
		},
		watch: {
			type: function() {
				console.log('watch-type', this.type)

			},
		},
		onReachBottom() {
			console.log('onReachBottom', onReachBottom)
			this.loadMoreImages()
		},
		methods: {
			init() {
				this.dataList = [];
				this.firstList = [];
				this.secondList = [];
				this.last = false;
				this.imgMargin = 0; // 图片边距: 单位px
				this.topArr = [0, 0]; // 存储每列的累积top
				this.pageSize = 8;
				this.page = 1;
				this.i = 0
				// debugger
			},


			// 显示未通过弹框
			openfail(item) {
				console.log(item);
				this.failText = item.auditRemark;
				this.isTips = true;
			},
			close() {
				this.isTips = false;
			},
			// 获取数据
			getGoodthingList() {
				// type userFabulousLists 赞过  userForumLists 嗮图
				if (this.type == 'userFabulousLists') {
					this.request_url = this.$api.community.userFabulousLists
				} else if (this.type == 'userForumLists') {
					this.request_url = this.$api.community.userForumLists
				} else {
					this.request_url = this.$api.community.forumLists
				}
				console.log('获取数据', this.type, this.request_url)
				this.$request(this.request_url, {
					page: this.page,
					pageSize: this.pageSize,
					...this.params,
				}).then((res) => {
					console.log('de', res)
					if (res.code == 0) {
						if (res.data.lists == null) {
							return wx.showToast({
								title: '非常抱歉没有找到相关信息',
								icon: 'none'
							})
						}
						this.page++;
						wx.hideLoading();
						this.last = res.data.last || false;
						this.dataList = res.data.lists;
						this.dataList.forEach((item, index) => {
							if (item.fabulous_num > 9999) {
								item.fabulous_num = parseFloat(item.fabulous_num / 10000).toFixed(1) + "万";
							} else {
								item.fabulous_num = item.fabulous_num;
							}
							item.use_fabulous = item.use_fabulous == 1 ? true : false
						});
						this.setDataList(this.dataList, 'faceimg');
					}
				});
			},
			/*
				函数说明:瀑布流获取图片高度计算方法,会把原数组拆分成两个数组返回
				参数说明:
				必填:
					arr:数组,里面有对象,对比对象里面的图片高度,返回两个数组
					attributeName:要根据数组里对象指定属性名称(图片的 Key)
				非必填:
					otherHeight:瀑布流的盒子其它组成部分的高度,例如点赞那列,因为瀑布流不单单是图片组成
					minHeight: 图片最小高度,如果没有图片,也会使用最小高度,相当于默认高度
					maxHeight:图片最大高度,高于就按照 maxHeight 算
			*/
			async setDataList(arr = [], attributeName, otherHeight = 100, minHeight = 10, maxHeight = 1000) {
				var arr1 = [],
					arr2 = [],
					imgMargin = 0, //图片边距
					height1 = 0, //第一组图片累计高度
					height2 = 0; //第二组图片累计高度

				// var getSystemInfo = await wx.getSystemInfo()
				for (let i = 0; i < arr.length; i++) {
					try {
						let heightData = await uni.getImageInfo({
							src: arr[i][attributeName]
						});
						let ImgHeight = heightData.length == 1 ? minHeight : heightData[1].height //如果长度等于1,就是图片有问题,这时候设置一个默认高度,如果长度等于2,下标1就有图片高度
						let imgWidth = heightData.length == 1 ? minHeight : heightData[1].width //如果长度等于1,就是图片有问题,

						let height = ImgHeight;
						if (height < minHeight) height = minHeight;
						if (height > maxHeight) height = maxHeight;

						if (height1 <= height2) {
							height1 += height
							this.firstList.push(arr[i])
						} else {
							height2 += height
							this.secondList.push(arr[i])
						}
						// console.log('arr2',height1,height2,arr1,arr2);
					} catch (err) {
						console.log('getImageInfo-err', err)
					}
				}
			},
			// 加载更多图片
			loadMoreImages: function() {
				console.log('加载更多图片', this.type)
				if (!this.last) {
					wx.showLoading({
						title: "加载中...",
					});
					this.getGoodthingList();
				}
				wx.hideLoading();
			},

			/** 预览图片 */
			// previewImg: function (e) {
			//   let index = e.currentTarget.dataset.index;
			//   let currentSrc = "";
			//   switch (e.currentTarget.dataset.type) {
			//     case "1":
			//       currentSrc = this.firstList[index].faceimg;
			//       break;
			//     case "2":
			//       currentSrc = this.secondList[index].faceimg;
			//   }
			//   wx.previewImage({
			//     urls: [currentSrc],
			//   });
			// },
			// 点赞
			giveLike(item, index, type) {
				if (this.like) {
					console.log(item);
					this.like = false;
					this.$request(this.$api.community.userToFabulous, {
						forum_id: item.id
					}).then(
						(res) => {
							if (res.code === 0) {
								item.use_fabulous = !item.use_fabulous;
								item.fabulous_num = item.use_fabulous ? item.fabulous_num + 1 : item.fabulous_num - 1;
								item.fabulous_num = item.fabulous_num > 9999 ? parseFloat(item.fabulous_num / 10000).toFixed(1) + "万" : item.fabulous_num;
								
								if (type == 'firstList') {
									this.firstList[index] = item
								} else {
									this.secondList[index] = item
								}
								this.like = true;
							}
						}
					);
				}
			},
			goDetails(item) {
				let navUrl = ''
				if (this.url == 'imgCommunity') {
					navUrl = "/pages/community/imgCommunity/SlideShowDetails?id=" + item.id;
				}
				this.$navTo.navigateTo({
					url: navUrl,
				})
			},
		},
	};
</script>

<style scoped lang="less">
	.page {
		width: 100%;
	}

	.main {
		width: 100%;
		background: #dce8fb;

		.view {
			width: 50%;
			display: inline-block !important;
			position: relative;
			vertical-align: top;
			padding: 6rpx;
			box-sizing: border-box;

			.content {
				border-radius: 4px;
				margin-bottom: 20rpx;
				box-sizing: border-box;
				background: white;

				.img-content {
					position: relative;

					.modle_mask {
						position: absolute;
						z-index: 9;
						color: #fff;
						left: 0;
						right: 0;
						top: 0;
						bottom: 0;
						background: rgba(0, 0, 0, 0.7);
						display: flex;
						justify-content: center;
						align-items: center;
					}

					.image {
						width: 100%;
						// height: 100%;
						border-top-right-radius: 4px;
						border-top-left-radius: 4px;
						box-sizing: border-box;
					}
				}

				.text {
					font-size: 26rpx;
					font-family: PingFangSC-Medium, PingFang SC;
					font-weight: 500;
					color: #333333;
					padding: 5px 8px 0 8px;
				}

				.price {
					font-size: 14px;
					color: #999999;
					padding: 5px 8px 5px 8px;
					box-sizing: border-box;
					display: flex;
					justify-content: space-between;
					align-items: center;

					.users {
						display: flex;
						align-items: center;

						.avatarUrl {
							width: 40rpx;
							height: 40rpx;
							border-radius: 20rpx;
							margin-right: 10rpx;
						}

						.nickName {
							min-width: 140rpx;
							max-width: 140rpx;
							overflow: hidden;
							white-space: nowrap;
							text-overflow: ellipsis;
						}
					}

					.give {
						display: flex;
						align-items: center;

						.giveXin {
							width: 20rpx;
							height: 20rpx;
							margin-right: 10rpx;
						}

						.giveNum {
							flex: 1;
						}
					}
				}
			}
		}
	}

	.modal_mask {
		box-sizing: border-box;
		position: fixed;
		left: 0;
		top: 0;
		width: 100vw;
		height: 100vh;
		z-index: 1002;
		background: rgba(0, 0, 0, 0.6);

		.modaltips {
			position: absolute;
			left: 50%;
			top: 50%;
			width: 575rpx;
			padding: 20rpx;
			transform: translate(-50%, -50%);
			background: linear-gradient(180deg, #92ddf6 0%, #59b8ea 100%);
			border-radius: 20px;
			box-sizing: border-box;
			display: flex;
			justify-content: center;
			align-items: center;
			overflow: initial;

			.modalPages {
				width: 530rpx;
				background: #ffffff;
				border-radius: 10px;
				padding: 128rpx 24rpx 30rpx;
				box-sizing: border-box;

				.coverImage {
					position: absolute;
					left: 50%;
					top: -200rpx;
					transform: translate(-50%, 0);
					width: 276rpx;
					height: 292rpx;
				}

				.modelText1 {
					text-align: center;
					font-size: 36rpx;
					font-family: PingFangSC-Medium, PingFang SC;
					font-weight: 500;
					color: #59b8ea;
					margin-bottom: 20rpx;
				}

				.modelText2 {
					font-size: 28rpx;
					font-family: PingFangSC-Regular, PingFang SC;
					font-weight: 400;
					color: #666666;
					line-height: 40rpx;
					white-space: normal;
					margin-bottom: 10rpx;
				}

				.back {
					position: absolute;
					left: 50%;
					bottom: -30%;
					transform: translate(-50%, 0);
					width: 280rpx;
					height: 66rpx;
					background: #59b8ea;
					box-shadow: 0px 2rpx 10rpx 2rpx #6b6e6f;
					border-radius: 20rpx;
					font-size: 28rpx;
					font-family: PingFangSC-Medium, PingFang SC;
					font-weight: 500;
					color: #ffffff;
					text-align: center;
					line-height: 66rpx;
				}
			}
		}
	}

	.approveImg {
		position: absolute;
		right: 6rpx;
		bottom: -60rpx;
		width: 60rpx;
		height: 60rpx;
	}
</style>