小程序中的瀑布流

1. 什么是瀑布流布局

瀑布流布局是一种常见的网页布局方式,也称为流式布局或瀑布式布局。它的特点是将卡片按照一定规则排列,使得页面整体呈现出类似瀑布般的流动感觉,给用户带来直观的视觉冲击。

这种排列方式最早是由Pinterest应用到其网站上的。之后,由于其它社交网站如Twitter、Facebook等的使用,瀑布流布局逐渐成为了一种非常受欢迎的设计风格。

瀑布流布局的特点:

元素按照一定规则排列,形成流式布局。

元素的大小和长宽比不固定,根据内容自适应。

通过JS等方式实现动态加载,让页面更加流畅。

2. 小程序中如何实现瀑布流布局

2.1 瀑布流布局原理

在瀑布流布局中,首先要确定每一列的宽度,然后计算每个元素之间的间隔。在布局的过程中,我们需要记录每一列的高度,以便后续元素的插入。

下面是一个简单的实现瀑布流布局的过程:

// 获取容器的宽度

const width = wx.getSystemInfoSync().windowWidth;

// 每列的宽度

const colWidth = (width - 30) / 2;

// 列数

const colCount = 2;

// 每列的高度

const colHeight = [];

// 遍历卡片,依次插入

cards.forEach((card, index) => {

// 计算元素的宽度和高度

const cardWidth = colWidth;

const cardHeight = (cardWidth / card.aspectRatio) || 200;

// 找到最短的一列,记录其高度

const minHeight = Math.min(...colHeight);

const minIndex = colHeight.indexOf(minHeight);

colHeight[minIndex] += cardHeight;

// 定位元素的位置

const left = minIndex * colWidth + 10 * (minIndex + 1);

const top = minHeight;

card.style = \`width: \${cardWidth}px; height: \${cardHeight}px; left: \${left}px; top: \${top}px;\`;

});

return cards;

以上代码中,我们定义了每列的宽度,然后遍历每个卡片进行插入。在插入前,计算出当前卡片的宽度和高度,然后找到列高度最短的一列,将卡片插入到该列中。

这里重点需要注意的是计算列高度的方式,需要找到最短的一列,并将当前卡片插入到该列中。

2.2 实现瀑布流布局的小技巧

在实现瀑布流布局的过程中,需要注意一些细节问题。

2.2.1 图片加载问题

在瀑布流布局中,图片通常是卡片的主要内容。因此,我们需要在插入卡片前,先加载图片,确保图片的宽高比例正确,避免布局出现问题。

const promiseList = cards.map((card) => {

return new Promise((resolve, reject) => {

wx.getImageInfo({

src: card.image,

success: (res) => {

card.aspectRatio = res.width / res.height;

resolve();

},

fail: reject,

});

});

});

return Promise.all(promiseList).then(() => {

// 布局卡片

}).catch((err) => {

// 图片加载出错

});

以上代码中,我们通过getImageInfo获取图片的宽高比例,然后将所有的promise包裹在Promise.all中,确保所有图片都加载完成后再进行布局,以避免出现计算错误的情况。

2.2.2 动态加载问题

在瀑布流布局中,由于卡片数量较多,因此需要采用动态加载的方式,防止页面卡顿。

一般而言,动态加载有两种方式,一种是在滚动到页面底部时,自动加载更多内容;另一种是在用户交互时,手动触发加载更多内容。

这里推荐采用自动加载的方式,用户体验更加友好。下面是一个简单的实现方式:

$onReachBottom() {

if (this.data.canLoadMore) {

this.loadMore();

}

},

loadMore() {

// 加载更多卡片

}

以上代码中,$onReachBottom方法是小程序提供的页面滚动到底部自动触发的方法。在该方法中,我们判断用户是否允许加载更多内容,如果是,则执行loadMore方法,从服务器获取更多卡片并加入到瀑布流布局中。

3. 总结

瀑布流布局是一种常见的网页布局方式,使页面整体呈现出类似瀑布般的流动感觉,给用户带来直观的视觉冲击。在小程序中,我们可以采用JS等方式实现动态加载,让页面更加流畅。在实现瀑布流布局的过程中,需要注意计算列高度、图片加载、动态加载等一些细节问题。

小程序瀑布流实现的代码示例:

// 瀑布流Layout组件

import { Layout } from '@minui/layout';

Component({

mixins: [Layout],

properties: {

cards: {

type: Array,

default: () => []

}

},

methods: {

async constructItemModel(item, index, onLoad) {

// 等待图片加载完毕

await new Promise(resolve => {

const image = wx.createImage();

image.onload = () => {

item.aspectRatio = image.width / image.height;

onLoad && onLoad();

resolve();

};

image.src = item.image;

});

// 开始布局

const itemWidth = (this.data.width - this.data.gutter * (this.data.columns - 1)) / this.data.columns;

const itemHeight = itemWidth / item.aspectRatio;

const minHeight = Math.min(...this.data.columnsHeight);

const minIndex = this.data.columnsHeight.indexOf(minHeight);

const left = minIndex * (itemWidth + this.data.gutter);

const top = minHeight;

this.setData({

['cards[' + index + '].style']: `width: ${itemWidth}px; height: ${itemHeight}px; left: ${left}px; top: ${top}px;`,

['columnsHeight[' + minIndex + ']']: minHeight + itemHeight + this.data.gutter

});

},

onResize({ width, cardCount }) {

const columns = Math.min(this.data.columns || 3, cardCount);

const columnWidth = (width - (columns - 1) * (this.data.gutter || 0)) / columns;

this.setData({

columns,

width,

columnWidth,

columnsHeight: new Array(columns).fill(0)

});

}

}

});

以上代码使用了minui组件库提供的瀑布流Layout组件,实现了自适应列数、卡片宽度、Gutter、高度等属性,兼容了避免重复调用加载更多方法的问题,提供了数据整体重设接口等。

使用示例:

<ml-layout cards="{{cards}}" loaded="{{loaded}}" total="{{total}}" on-load-more="{{loadMore}}" on-resize="{{onResize}}" gutter="10" columns="2" >

<view slot="card" style="{{card.style}}">

<image src="{{card.image}}" mode="aspectFit" />

</view>

</ml-layout>

其中,ml-layout是瀑布流Layout组件的名称;cards、loaded、total、loadMore、onResize、gutter、columns等都是该组件支持的属性和方法。

上述代码可以供开发者参考使用,同时在实际开发中,需要根据具体需求进行实现和调整。