我是靠谱客的博主 精明春天,最近开发中收集的这篇文章主要介绍小程序瀑布流实现,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

什么是瀑布流布局

瀑布流布局,一般等宽,不等高的列表排列

原理是找出高度之和最小的那一列,在高度最小列继续添加元素

可以通过 absolute 定位实现,动态计算每一项的 topleft

在这里插入图片描述

封装瀑布流方法

function getAllRect(context, selector) {
  return new Promise(function (resolve) {
    wx.createSelectorQuery()
      .in(context)
      .selectAll(selector)
      .boundingClientRect()
      .exec(function (rect) {
        if (rect === void 0) {
          rect = []
        }
        return resolve(rect[0])
      })
  })
}

/**
 * 瀑布流
 * @param {*} context 页面或组件this对象
 * @param {string} selector 选择器
 * @param {Object} options
 * @param {number=375} options.width 屏幕宽度
 * @param {number=2} options.column 列数
 * @param {number|string} options.gap 每列直接的间隙
 * @param {number=0} options.padding 整个列表左右的padding
 * @param {number=0}
 * @returns {Array} 计算每项的top、left、height的数组
 */
async function waterFall(context, selector, options = {}) {
  let items = await getAllRect(context, selector)
  if (items.length <= 0) return []
  let { gap = 15, column = 2, padding = 0, width = 375, firstColumnToTop = 0 } = options
  // 1- 确定列数  = 页面的宽度 / 图片的宽度,单例的宽度
  let itemWidth = items[0].width
  // 定义每一列之间的间隙 px
  if (gap === 'auto') {
    gap = (width - itemWidth * column) / (column - 1)
  }
  let _columnHeightArr = [] // 保存每列高度
  let result = []

  for (let i = 0, len = items.length; i < len; i++) {
    if (i < column) {
      // 2- 确定第一行
      let top = firstColumnToTop
      let left = (itemWidth + gap) * i + padding
      // 瀑布流列表左右padding
      if (i === 0 || i === len - 1) {
        left = padding
      }
      _columnHeightArr.push(items[i].height - top)
      result.push({
        top,
        left,
        height: items[i].height,
      })
    } else {
      // 其他行
      // 3- 找到数组中最小高度  和 它的索引
      let minHeight = Math.min(..._columnHeightArr)
      let minIndex = _columnHeightArr.findIndex((item) => item === minHeight)
      // 4- 设置下一行的第一个盒子位置
      // top值就是最小列的高度 + gap
      result.push({
        top: _columnHeightArr[minIndex] + gap,
        left: result[minIndex].left,
        height: items[i].height,
      })

      // 5- 修改最小列的高度
      // 最小列的高度 = 当前自己的高度 + 拼接过来的高度 + 间隙的高度
      _columnHeightArr[minIndex] = _columnHeightArr[minIndex] + items[i].height
    }
  }

  return result
}

使用

vim demo.wxml

    <!--需要子元素撑大父元素高度的情况,才需要设置height-->
    <view class="goods_list flex flex-wrap relative" style="width:100%;height:{{height}}">
        <block wx:for="{{list}}" wx:key="index">
          <view class="goods_item" style="position:absolute;top:{{ item.top }}px;left:{{ item.left }}px"
                bindtap="handleItem" data-item="{{item}}">
            <view class="goods_img">
              <goodsImage detail="{{ {imgUrl:item.goodsIcon} }}" isAllowCash="{{true}}">
              </goodsImage>
            </view>
            <view class="goods_mes">
              <view class="goods_name g-t-over2">{{item.goodsName}}</view>
              <view class="goods_price">{{item.price}}</view>
            </view>
          </view>
        </block>
    </view>

vim demo.js

// 需要在节点加载到页面后调用
onReady() {
  const { screenWidth, list } = this.data
  waterFall(this, '.goods_item', { width: screenWidth, gap: 'auto' }).then((arr) => {
    if (!arr.length) return
    let lastNode = arr[arr.length - 1]
    let height = lastNode.top + lastNode.height + 'px'
    this.setData({
      list: list.map((item, index) => ({ ...item, ...arr[index] })),
      height,
    })
  })
}

效果

在这里插入图片描述

小结

既然都封装成函数了,为什么不封装成组件调用呢?

组件调用可以参考这个小程序的瀑布流组件me-waterfall

我看了这个组件的源码,用到组件间关系来实现瀑布流结构,整个瀑布流组件内部也需要父子组件关系,父组件监听子组件插入元素,获取元素的动态高度,往高度最小列添加新元素。

但是我引入使用,在组件内使用me-waterfall 组件,组件间关系方法 linked 不生效,官方论坛也找不到原因,便弃用。
类似这样的结构:

<!--page.wxml-->
<view>
	<goodsList />
</view

<!--goodsList.wxml-->
<view>
	<me-waterfall>
	  <me-waterfall-item wx:for="{{list}}" wx:key="index">
	    <image src="{{item.imgUrl}}" style="width:100%;height:{{item.height}}px" />
	  </me-waterfall-item>
	</me-waterfall>
</view

于是,自己封装一个方法使用。便有了此文。

封装成方法也有优点,不需要引入组件,简单引入一下方法调用即可。

最后

以上就是精明春天为你收集整理的小程序瀑布流实现的全部内容,希望文章能够帮你解决小程序瀑布流实现所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(55)

评论列表共有 0 条评论

立即
投稿
返回
顶部