uniapp实现瀑布流列表
程序员文章站
2022-03-19 21:51:20
...
效果图:
瀑布流
瀑布流是很常见的一种布局方式,像一些图片展示网站,购物网站中最为常见。瀑布流将显示区域划分为固定宽度的几栏。可以保持一致的图片或者div展示区域的宽度,自适应其高度,显示元素的顺序从左到右,自上而下排列。显示效果极好,空间利用率高。
实现逻辑:
本例中采用两栏瀑布流布局,分别用数组goodsLeftList和goodsRightList储存左右两栏要显示的card(card表示显示的元素),goodsLeftListHeight和goodsRightListHeight表示左右两栏的高度;
每加载一张图片,要进行自适应处理,计算显示的高度,然后把图片加到栏高更低的一栏中,更新这一栏的高度,初始化时,加载一张图片,
代码
html代码:主要使用@load="onImageLoad"给图片绑定事件,该事件当图片载入完毕时,发布到 AppService 的事件名,事件对象event.detail = {height:‘图片高度px’, width:‘图片宽度px’}
<view class="goodsContent">
<view class="goodsLeftList" >
<view class="goodsItem" v-for="item in goodsLeftList">
<image :src="item.image_url" @load="onImageLoad" mode="widthFix"></image>
<view class="goodsName">{{item.name}}</view>
<view class="goodsPrice">
<image src="../../static/img/common/price.png" mode="widthFix"></image>
<text>{{item.priceNow}}</text>
</view>
</view>
</view>
<view class="goodsRightList">
<view class="goodsItem" v-for="item in goodsRightList">
<image :src="item.image_url" @load="onImageLoad" mode="widthFix"></image>
<view class="goodsName">{{item.name}}</view>
<view class="goodsPrice">
<image src="../../static/img/common/price.png" mode="widthFix"></image>
<text>{{item.priceNow}}</text>
</view>
</view>
</view>
</view>
data中的数据
goodsList:[
{
name:"高配版热水器",
priceNow : "1499.00",
image_url:"goodImg/1.jpg",
},
{
name:"速热高温煮水蛋",
priceNow : "499.00",
image_url:baseUrl.local_url+"goodImg/2.jpg",
},
{
name:"速热高温煮水蛋",
priceNow : "499.00",
image_url:baseUrl.local_url+"goodImg/3.jpg",
},
],
goodsListCount:0, //加载第i张图片
// 左侧商品列表
goodsLeftList:[],
goodsLeftListHeight : 0,
// 右侧商品列表
goodsRightList:[],
goodsRightListHeight : 0,
method中放:
// 图片绑定事件,通过比较左右列表高度,实现瀑布流展示
onImageLoad: function(e){
let divWidth = 295; //显示的单栏宽度,我设为295rpx
let oImgW = e.detail.width; //图片原始宽度
let oImgH = e.detail.height; //图片原始高度
let rImgH = divWidth*oImgH/oImgW; //根据宽高比计算当前载入的图片的高度
if(rImgH > 600){
rImgH = 600; //限制图片最高600rpx,可在css中添加 max-height:600rpx;
}
if(this.goodsListCount==0){
this.goodsLeftListHeight += rImgH; //第一张图片高度加到goodsLeftListHeight
this.goodsListCount++; //图片索引加1
this.goodsRightList.push(this.goodsList[this.goodsListCount]); //添加第二张图片到goodsRightList数组,因为第一张已经初始化到左侧列表中
}else{
this.goodsListCount++; //图片索引加1
if(this.goodsLeftListHeight > this.goodsRightListHeight){ //把图片的高度加到目前高度更低的栏中
this.goodsRightListHeight += rImgH; //第二张图片高度加到goodsRightListHeight
}else{
this.goodsLeftListHeight += rImgH;
}
if(this.goodsListCount<this.goodsList.length){ //根据目前的栏高,把下一张图片,push到低的那栏
if(this.goodsLeftListHeight > this.goodsRightListHeight){
this.goodsRightList.push(this.goodsList[this.goodsListCount]);
}else{
this.goodsLeftList.push(this.goodsList[this.goodsListCount]);
}
}
}
},
// 向商品列表添加第一张图片
async waterfallImage() {
this.goodsLeftList.push(this.goodsList[0]);
},
css样式
/* 商品列表 */
.goodsContent{
width: 100%;
background: #f7f7f7;
display: flex;
justify-content: center;
}
.goodsLeftList{
margin:0 10rpx 0 40rpx;
width: 325rpx;
}
.goodsRightList{
margin:0 40rpx 0 10rpx;
width: 325rpx;
}
.goodsItem{
background: #FFFFFF;
width:325rpx;
margin-bottom: 15rpx;
}
.goodsItem image{
max-height: 600rpx;
height: auto;
width:295rpx;
padding: 15rpx 15rpx 5rpx;
}
.goodsName{
font-size: 28rpx;
color: #2e2e2e;
padding: 0 20rpx;
overflow: hidden;
text-overflow: ellipsis;
display:-webkit-box;
-webkit-line-clamp:2;
-webkit-box-orient:vertical;
}
.goodsPrice{
color: #ffac29;
font-size: 24rpx;
padding: 0 15rpx;
}
.goodsPrice image{
width: 20rpx;
height: 20rpx;
padding: 0 5rpx;
}