小程序简单两栏瀑布流效果的实现


Posted in Javascript onDecember 18, 2019

瀑布流又称瀑布流式布局,是比较流行的一种网站页面布局方式。视觉表现为参差不齐的多栏布局,即多行等宽元素排列,后面的元素依次添加到其后,等宽不等高,根据图片原比例缩放直至宽度达到我们的要求,依次放入到高度最低的那一栏。

先上代码:https://developers.weixin.qq.com/s/Fgm5s1mz7Wdm

所谓简单,是指只考虑图片,图片之外的其他元素高度固定,不在考虑范围内。

说一下基本的实现思路:
1、加载列表数据
2、在一个隐藏的view中加载图片,通过image组件的bindload获取图片的实际宽高并存储
3、等所有图片加载完成后遍历列表,将图片插入到高度低的那一栏,同时更新该栏高度

我也考虑过在第二步bindload获取到宽高后就直接插入到栏位中,但是会出现小的图片先加载完先出现到页面中,虽然瀑布流不是普通的列表那样的排序,但是也不能小的图片在上面这样太乱顺序,所以就改成了获取宽高先存储,等所有图片加载完成后再往页面上渲染。

来看看实际的代码

不需要渲染到wxml中的数据,我放到了jsData中,主要是两栏的高度和是否在加载数据的标记。
tempPics是第一次加载的数据,临时存放,用于加载图片宽高
columns是两个栏位的实际展示数据

jsData: {
 columnsHeight: [0, 0],
 isLoading: false
},
data: {
 columns: [
  [],
  []
 ],
 tempPics: []
}

1、加载列表数据

这一步没什么好说的,主要是触发方式,我的代码里是放在页面加载以及拉大页面底部时触发

onLoad: function() {
 this.loadData()
},
onReachBottom: function() {
 this.loadData()
}

加载后将列表数据存到tempPics中,用于页面加载获取宽高

2、在一个隐藏的view中加载图片,通过image组件的bindload获取图片的实际宽高并存储

<view class="hide">
 <image wx:for="{{tempPics}}" src="{{item.pic}}" bindload="loadPic" binderror="loadPicError" data-index="{{index}}" />
</view>

主要是image组件的bindload来获取实际宽高,这里还增加了binderror,防止出现图片加载出错的时候卡死

loadPic: function(e) {
 var that = this,
  data = that.data,
  tempPics = data.tempPics,
  index = e.currentTarget.dataset.index
 if (tempPics[index]) {
  //以750为宽度算出相对应的高度
  tempPics[index].height = e.detail.height * 750 / e.detail.width
  tempPics[index].isLoad = true
 }
 that.setData({
  tempPics: tempPics
 }, function() {
  that.finLoadPic()
 })
}

获取到宽高后,以750为宽度计算出相对应的高度并存储,然后增加一个加载完成的标记。加载出错后就强制高度为750,这样展示的时候就是一个正方形。

单个图片加载完成并存储后调用finLoadPic方法来判断所有图片是否都加载完成。

遍历列表,只要有一个图片没有加载完成的标记,就判断为没有加载完成。

加载完成后进入下一步。

finLoadPic: function() {
 var that = this,
  data = that.data,
  tempPics = data.tempPics,
  length = tempPics.length,
  fin = true
 for (var i = 0; i < length; i++) {
  if (!tempPics[i].isLoad) {
   fin = false
   break
  }
 }
 if (fin) {
  wx.hideLoading()
  if (that.jsData.isLoading) {
   that.jsData.isLoading = false
   that.renderPage()
  }
 }
}

3、等所有图片加载完成后遍历列表,将图片插入到高度低的那一栏,同时更新该栏高度

这里需要再便利一遍列表,根据当前栏位的高度情况,将图片插入到高度底的那一栏,同时把这一栏高度加上当前图片的高度(不是实际高度,是上一步以750为宽度算出来的高度)

renderPage: function() {
 var that = this,
  data = that.data,
  columns = data.columns,
  tempPics = data.tempPics,
  length = tempPics.length,
  columnsHeight = that.jsData.columnsHeight,
  index = 0
 for (var i = 0; i < length; i++) {
  index = columnsHeight[1] < columnsHeight[0] ? 1 : 0
  columns[index].push(tempPics[i])
  columnsHeight[index] += tempPics[i].height
 }
 that.setData({
  columns: columns,
  tempPics: []
 })
 that.jsData.columnsHeight = columnsHeight
}

在wxml中展示的时候image组件的mode要使用widthFix,同时wxss中图片的高度和宽度一样,这样加载出错的图片可以正方形展示

11月21日增加:

根据网友@杨泉的建议,也尝试了使用wx.getImageInfo来获取图片的宽高(点击查看具体代码),代码也精简了很多。但是实际比较下来速度要比用image组件慢,初步推测原因是wx.getImageInfo会返回本地路径,多了写本地临时文件的时间

ps:用到瀑布流的地方,最好能后端直接返回图片的宽高,省去小程序端获取宽高的麻烦

再ps:我个人并不建议小程序端使用瀑布流

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JS 日期验证正则附asp日期格式化函数
Sep 11 Javascript
jQuery EasyUI 中文API Layout(Tabs)
Apr 27 Javascript
JavaScript中两个感叹号的作用说明
Dec 28 Javascript
node.js实现BigPipe详解
Dec 05 Javascript
基于jQuery仿淘宝产品图片放大镜代码分享
Jun 23 Javascript
js实现跨域访问的三种方法
Dec 09 Javascript
实例讲解避免javascript冲突的方法
Jan 03 Javascript
基于Vue实例对象的数据选项
Aug 09 Javascript
Angular2整合其他插件的方法
Jan 20 Javascript
jQuery的Ajax接收java返回数据方法
Aug 11 jQuery
原生javascript中this几种常见用法总结
Feb 24 Javascript
基于JS实现table导出Excel并保留样式
May 19 Javascript
js数据类型转换与流程控制操作实例分析
Dec 18 #Javascript
vue不操作dom实现图片轮播的示例代码
Dec 18 #Javascript
使用JS来动态操作css的几种方法
Dec 18 #Javascript
基于ts的动态接口数据配置的详解
Dec 18 #Javascript
H5实现手机拍照和选择上传功能
Dec 18 #Javascript
如何使用webpack打包一个库library的方法步骤
Dec 18 #Javascript
js实现上传图片并显示图片名称
Dec 18 #Javascript
You might like
2.PHP入门
2006/10/09 PHP
Yii入门教程之目录结构、入口文件及路由设置
2014/11/25 PHP
浅析PHP中的闭包和匿名函数
2017/12/25 PHP
PHP程序员必须知道的两种日志实例分析
2020/05/14 PHP
javascript实现的距离现在多长时间后的一个格式化的日期
2009/10/29 Javascript
jQuery 表单验证扩展代码(二)
2010/10/20 Javascript
如何获取select下拉框的值(option没有及有value属性)
2013/11/08 Javascript
使用jQuery制作遮罩层弹出效果的极简实例分享
2016/05/12 Javascript
15个值得开发人员关注的jQuery开发技巧和心得总结【经典收藏】
2016/05/25 Javascript
Bootstrap.css与layDate日期选择样式起冲突的解决办法
2017/04/07 Javascript
vue-cli扩展多模块打包的示例代码
2018/04/09 Javascript
vue多页面开发和打包正确处理方法
2018/04/20 Javascript
vue以组件或者插件的形式实现throttle或者debounce
2019/05/22 Javascript
Vue实现穿梭框效果
2020/09/30 Javascript
针对Vue路由history模式下Nginx后台配置操作
2020/10/22 Javascript
关于小程序优化的一些建议(小结)
2020/12/10 Javascript
[42:36]DOTA2上海特级锦标赛B组败者赛 VG VS Spirit第二局
2016/02/26 DOTA
[01:06:54]DOTA2-DPC中国联赛 正赛 RNG vs Dragon BO3 第一场 1月24日
2021/03/11 DOTA
python 域名分析工具实现代码
2009/07/15 Python
python里对list中的整数求平均并排序
2014/09/12 Python
通过C++学习Python
2015/01/20 Python
python实现根据月份和日期得到星座的方法
2015/03/27 Python
使用Python脚本将文字转换为图片的实例分享
2015/08/29 Python
Python简单读取json文件功能示例
2017/11/30 Python
Python3.5基础之变量、数据结构、条件和循环语句、break与continue语句实例详解
2019/04/26 Python
pyqt5、qtdesigner安装和环境设置教程
2019/09/25 Python
wxpython多线程防假死与线程间传递消息实例详解
2019/12/13 Python
Python中logging日志记录到文件及自动分割的操作代码
2020/08/05 Python
详解python命令提示符窗口下如何运行python脚本
2020/09/11 Python
Python 列表反转显示的四种方法
2020/11/16 Python
南非领先的在线旅行社:Travelstart南非
2016/09/04 全球购物
英国第一家领先的在线处方眼镜零售商:Glasses Direct
2018/02/23 全球购物
Intersport西班牙:在线体育商店
2019/11/06 全球购物
年终总结会议主持词
2014/03/17 职场文书
演讲稿:​快乐,从不抱怨开始!
2019/04/02 职场文书
解决pycharm下载库时出现Failed to install package的问题
2021/09/04 Python