效果图:
说明:
函数说明:传入一个数组,循环获取图片高度,会根据把原数组拆分成两个数组,放在两列,
计算单列累计高度,对比高度值的大小,实现瀑布流的布局,
由于获取图片高度需要一定的时间,所以使用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>