素材巴巴 > 程序开发 >

vue简单实现瀑布流

程序开发 2023-09-08 15:30:11

瀑布流原理

瀑布流,即多行等宽元素排列,后面的元素依次添加到其后,等宽不等高,根据图片原比例缩放宽高;

瀑布流布局特点,从第2行开始,接下来的每一张图片都会放在现有列中高度最低的那一列,如下图:

再继续排列下去,第6张图片应该放在第1列,以此类推,如下图:

所以每次排列一张图片时,就需要判断一次现有列中累计高度最小的列,下一张图片就排在哪一列,即瀑布流算法去判断图片的确定位置;

实现思路

目前常见瀑布流实现都采用定位布局+js计算位置(left,top)方式,搭配后端返回图片真实宽高,实现起来方便,效果更好;

  1. 设定列数,列间距,根据容器宽度计算出每列宽度;
  2. 定义行间距;
  3. 遍历元数据,生成最终瀑布流list;

实现代码

1、设定列数,列间距,根据容器宽度计算出每列宽度;

@Prop({ type: Number, default: 2 }) private readonly columnNum?: number; // 列数@Prop({ type: Number, default: 10 }) private readonly columnSpan?: number; // 列间距,只有列与列之间才有间距,每行第一列的左边距/最后一列的右边距由外部容器控制private columnWidth = 0; // 列宽mounted() {// 获取容器宽度const containerWidth = this.$el.clientWidth;const columnNum = this.columnNum as number;const columnSpan = this.columnSpan as number;// 获取列宽度this.columnWidth =(containerWidth - (columnNum - 1) * columnSpan) / columnNum;
 }

2、定义行间距;

@Prop({ type: Number, default: 20 }) private readonly rowSpan?: number; // 行间距,只有行与行之间才有间距,第一行的上边距/最后一行的下边距由外部容器控制

3、遍历元数据,生成最终瀑布流list;

@Prop({ type: Array, required: true }) private readonly list?: Item[]; // 瀑布流数据private containerHeight = 0; // 容器高度private get waterfallFlowList(): WaterfallFlowItem[] | undefined {const columnWidth = this.columnWidth;if (columnWidth === 0) return [];const columnHeightList: number[] = [];const columnNum = this.columnNum as number;const columnSpan = this.columnSpan as number;const rowSpan = this.rowSpan as number;const list = this.list?.map((i, d) => {// 得到每一个item的列高const columnHeight = (columnWidth * i.height) / i.width;const item = { ...i, columnHeight: columnHeight, top: 0, left: 0 };if (d < columnNum) {item.left = (columnWidth + columnSpan) * d;columnHeightList.push(columnHeight);} else {// 获取最小高度const minColumnHeight = Math.min(...columnHeightList);const minColumnHeightIndex = columnHeightList.findIndex(i => i === minColumnHeight);item.left = (columnWidth + columnSpan) * minColumnHeightIndex;item.top = minColumnHeight + rowSpan;columnHeightList[minColumnHeightIndex] =minColumnHeight + rowSpan + columnHeight;}return item;});// 获取容器高度const maxTop = Math.max(...(list?.map(i => i.top) || []));const maxItem = list?.find(i => i.top === maxTop);if (maxItem) this.containerHeight = maxTop + maxItem.columnHeight;return list;}

最终效果图

完整代码

调用例子

{{ index + 1 }}

 


标签:

素材巴巴 Copyright © 2013-2021 http://www.sucaibaba.com/. Some Rights Reserved. 备案号:备案中。