在实际开发中,有很多时候会用到瀑布流布局,应用场景最多的可能要属图片展示了。
下面记录一下在小程序中如何实现瀑布流布局。(都是美女小姐姐的图片->_->)
一、图片分列排列计算
我们要实现一个固定排列成两列的布局,将图片动态加载进来,而加载的图片会根据图片的尺寸自动决定排左还是排右。
/* 瀑布流 */
/*单张图片*/
.img_item {
width: 48%;
margin: 1%;
display: inline-block;
vertical-align: top;
}
以上是单张图片的样式,接下来是在js中通过代码来计算图片的排列顺序。
首先定义两个变量:col1H、col2H,用来计算排列顺序。
let col1H = 0;
let col2H = 0;
然后,在data中定义一些会用到的变量。
scrollH: 0,
imgWidth: 0,//图片宽度
loadingCount: 0,//图片总数
images: [],//存放图片数据
col1: [],//左
col2: [],//右
在onload方法中,用下面的代码计算一些变量的值
wx.getSystemInfo({
success: (res) => {
let ww = res.windowWidth;
let wh = res.windowHeight;
let imgWidth = ww * 0.48;
let scrollH = wh;
this.setData({
scrollH: scrollH,
imgWidth: imgWidth
});
this.loadImages();
}
})
最后,通过具体的代码计算出哪些图片放左边,哪些图片放右边。
//通过计算,将图片分成两列
onImageLoad: function(e) {
let imageId = e.currentTarget.id;
let oImgW = e.detail.width; //图片原始宽度
let oImgH = e.detail.height; //图片原始高度
let imgWidth = this.data.imgWidth; //图片设置的宽度
let scale = imgWidth / oImgW //比例计算
let imgHeight = oImgH * scale; //自适应高度
let images = this.data.images;
let imageObj = null;
for (let i = 0; i < images.length; i++) {
let img = images[i];
if (img.id === imageId) {
imageObj = img;
break;
}
}
imageObj.height = imgHeight;
let loadingCount = this.data.loadingCount - 1;
let col1 = this.data.col1;
let col2 = this.data.col2;
if (col1H <= col2H) {
col1H += imgHeight;
col1.push(imageObj);
} else {
col2H += imgHeight;
col2.push(imageObj);
}
let data = {
loadingCount: loadingCount,
col1: col1,
col2: col2
};
if (!loadingCount) {
data.images = [];
}
this.setData(data);
},
loadImages: function() {
let images = [
{img:'../../images/1.jpg',height:0},
{ img: '../../images/2.jpg', height: 0 },
{ img: '../../images/3.jpg', height: 0 },
{ img: '../../images/4.jpg', height: 0 },
{ img: '../../images/5.jpg', height: 0 },
{ img: '../../images/6.jpg', height: 0 },
{ img: '../../images/7.jpg', height: 0 },
{ img: '../../images/8.jpg', height: 0 },
{ img: '../../images/9.jpg', height: 0 },
{ img: '../../images/10.jpg', height: 0 },
{ img: '../../images/11.jpg', height: 0 },
{ img: '../../images/12.jpg', height: 0 },
{ img: '../../images/13.jpg', height: 0 },
{ img: '../../images/14.jpg', height: 0 }
]
let baseId = "img-" + (+new Date());
for (let i = 0; i < images.length; i++) {
images[i].id = baseId + "-" + i;
}
_this.setData({
loadingCount: images.length,
images: images,
})
},
二、布局
<view class="view-fp-container">
<!--瀑布流-->
<view style="display:none">
<image wx:for="{{images}}" wx:key="id" id="{{item.id}}" src="{{item.img}}" bindload="onImageLoad"></image>
</view>
<scroll-view scroll-y="true" style="height:{{scrollH}}px" bindscrolltolower="scrollLower">
<view style="width:100%">
<view class="img_item">
<view style="background-color:#fff;margin-bottom:10rpx;" wx:for="{{col1}}" wx:key="id">
<image src="{{item.img}}" style="width:100%;height:{{item.height}}px" mode='aspectFill'></image>
</view>
</view>
<view class="img_item">
<view style="background-color:#fff;margin-bottom:10rpx;" wx:for="{{col2}}" wx:key="id">
<image src="{{item.img}}" style="width:100%;height:{{item.height}}px" mode='aspectFill'></image>
</view>
</view>
</view>
</scroll-view>
</view>
三、样式
page {
background-color: #f2f2f2;
}
.view-fp-container {
display: flex;
flex-direction: column;
margin: 0 10rpx;
}
/* 瀑布流 */
.img_item {
width: 48%;
margin: 1%;
display: inline-block;
vertical-align: top;
}
四、最终效果
(注:展示效果和图片数量、宽高有关系)