首先 看下效果图:
第一步 初始化参数:
let params = {
imgList: [], // 服务器返回的图片list 集合
screenWidth: document.body.clientWidth, // 屏幕宽度
waterfallImgList: [], // 流图片数组
waterfallImgWidth: 0, // 每张图片图片宽度
waterfallImgCol: 2, // 屏幕横向显示两张图片
waterfallImgRight: 10, // 每张图片居右间距
waterfallImgBottom: 10, // 每张图片居底部间距
waterfallDeviationHeight: [], // 每张图片的偏移高度
}
第二步瀑布流核心计算
// 计算每个图片的宽度或者是列数
calculationWidth () {
const that = this
// 获取 瀑布流展示 的dom 内容宽度
let domWidth = document.getElementById('v-waterfall').scrollWidth
if (!that.waterfallImgWidth && that.waterfallImgCol) {
// 判断 图片宽度为0 并且 设置列数 时, 计算图片宽度 (屏幕宽度 / 图片列数 - 图片间距左右和为20 )
that.waterfallImgWidth = (that.screenWidth / that.waterfallImgCol - 20)
} else if (that.waterfallImgWidth && !that.waterfallImgCol) {
// 判断 图片宽度存在且 图片列数 为假时, 计算图片展示列数 并向下取整(内容宽度/ (图片宽度 + 图片居右间距))
that.waterfallImgCol = Math.floor(domWidth / (that.waterfallImgWidth + that.waterfallImgRight))
}
// 初始化偏移高度数组
that.waterfallDeviationHeight = Array(that.waterfallImgCol).fill(0)
that.imgPreloading()
},
// 图片预加载
imgPreloading () {
const that = this
that.imgList.forEach((item, i) => {
// 创建图片对象 并设置图片 添加到瀑布流集合中
let aImg = new Image()
aImg.src = item.photo
aImg.onload = aImg.onerror = (e) => {
let imgData = {
height: that.waterfallImgWidth / aImg.width * aImg.height,
photo: item.photo
}
that.waterfallList.push(imgData)
that.rankImg(imgData)
}
})
},
// 瀑布流布局
rankImg (imgData) {
// 解构赋值操作
let {waterfallImgWidth, waterfallImgRight, waterfallImgBottom, waterfallDeviationHeight, waterfallImgCol} = params
let minIndex = this.filterMin()
imgData.top = waterfallDeviationHeight[minIndex]
imgData.left = minIndex * (waterfallImgRight + waterfallImgWidth)
waterfallDeviationHeight[minIndex] += imgData.height + waterfallImgBottom
},
/**
* 找到最短的列并返回下标
* @returns {number} 下标
*/
filterMin () {
const min = Math.min.apply(null, this.waterfallDeviationHeight)
return this.waterfallDeviationHeight.indexOf(min)
}
第三步 页面加载 ,css
<div class="v-waterfall-content" id="v-waterfall" v-show="!listLoading">
<div v-for="(img,index) in waterfallList" @click="lookImg(index)" :key="index" class="v-waterfall-item"
:style="{top:img.top+'px',left:img.left+'px',width:waterfallImgWidth+'px',height:img.height}">
<van-image :src="img.photo" alt=""/>
</div>
</div>
.v-waterfall-content{
margin-top: 20px;
width: 100%;
height: 100%;
position: relative;
}
.v-waterfall-item{
float: left;
position: absolute;
}
.v-waterfall-item img{
width: 100%;
height: 100%;
}
.v-waterfall-item:last-child{
padding-bottom: 100px;
}