1 瀑布流是什么?
瀑布流布局是比较流行的一种网站页面布局,有一个专业的英文名称 Masonry Layouts。
瀑布流布局已经有好多年的历史了,其中最典型的例子是:Pinterest网站。
瀑布流布局其核心是基于一个网格的布局,由宽度相等高度不定的元素组成的参差不齐的多栏布局,随着页面的向下滚动,新的元素自动附加到最短的一列,以此不断的加载。
2 瀑布流实现原理:
当有新的元素需要展示时,每次都是寻找各列之中高度最小的一列,并将新的元素添加到该列后面。
3 代码实现:
最终时间的效果为:

3.1 确定每一列的宽度
在小程序中,引入了尺寸单位:rpx(responsive pixel),可以根据屏幕宽度进行自适应。转换规则如下:

而后端返回的图片的宽度和高度的单位一般都是px,如何正确的转化,才能计算出正确的缩放比例以及缩放后的图片尺寸?
(1)统一计算单位。
(2)计算每一列的宽度waterfallWidth。
假设设置每一列的宽度为 328rpx,原始图片的宽为picWidth,高为picHeight。
首页把宽度转为px可得每一列的宽度:
waterfallWidth= 328 * (Math.floor((wx.getSystemInfoSync().windowWidth / 750) * 100) / 100) px
3.2 计算最终图片展示时的高度
根据图片最终展示的宽度为 waterfallWidth,动态计算每张图片对应的高度:
(1)首先计算缩放比例:
scale = waterfallWidth / picWidth;(2)缩放后的图片高度:
afterPicHeight = picHeight * scale;3.3 计算会影响列高度的其他元素高度
要正确的寻找最短的那一列,除了图片,图片上下区域如果非固定的,可变动的,会影响列高度的元素都需要列入考虑。
此处,需要额外考虑的是图片描述区域的高度。
(1)计算图片描述区域行数:
/**
* 参数说明:
* text:计算的文本
* num:一行的字节数
* return:一行一行组成的数组
*/
textByteLength(text, num) {
let strLength = 0;
let rows = 1;
let str = 0;
const textArr = [];
for (let i = 0; i < text.length; i++) {
if (text.charCodeAt(i) > 255) {
strLength += 2;
if (strLength > rows * num) {
strLength++;
textArr.push(text.slice(str, i));
str = i;
rows++;
}
} else {
strLength++;
if (strLength > rows * num) {
textArr.push(text.slice(str, i));
str = i;
rows++;
}
}
}
textArr.push(text.slice(str, text.length));
return textArr;
}(2)已知一行的高度为 15rpx,则可获得描述区域的高度为
15*textArr.length。3.4 记录维护每一列的最终高度
3.5 下滑不断加载填充
为了提高性能,减少每一次 setData 的数据量,选择二位数组的存储结构。
this.setData({
['phototListLeft[' + page + ']']: phototListLeft,
['phototListRight[' + page + ']']: phototListRight
});本实例亮点:
- 使用二维数组存储,减少每次 setData 的数据量,有效提高了性能;
- 图片的描述内容也是随机的,高度不固定,通过动态计算,获取图片描述区域的高度;
- 因为图片宽度单位为px,故为了在各个手机能完美适配,通过单位转化,完美适配;
- 对每张图片显示前,设置随机的填充背景。