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


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 相关文章推荐
JQuery入门——用映射方式绑定不同事件应用示例
Feb 05 Javascript
JS正则表达式获取分组内容的方法详解
Nov 15 Javascript
javascript中为某个元素指定事件的三种方式
Aug 07 Javascript
JQuery操作元素的css样式
Mar 09 Javascript
jQuery form插件之ajaxForm()和ajaxSubmit()的可选参数项对象
Jan 23 Javascript
Bootstrap Table的使用总结
Oct 08 Javascript
微信小程序 删除项目工程实现步骤
Nov 10 Javascript
Node.js用readline模块实现输入输出
Dec 16 Javascript
Vue Ajax跨域请求实例详解
Jun 20 Javascript
node中Express 动态设置端口的方法
Aug 04 Javascript
vue框架制作购物车小球动画效果实例代码
Sep 26 Javascript
vue-cli4.x创建企业级项目的方法步骤
Jun 18 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
《PHP边学边教》(04.编写简易的通讯录――视频教程1)
2006/12/13 PHP
php文件打包 下载之使用PHP自带的ZipArchive压缩文件并下载打包好的文件
2012/06/13 PHP
[原创]PHP实现逐行删除文件右侧空格的方法
2015/12/25 PHP
yii去掉必填项中星号的方法
2015/12/28 PHP
简单谈谈javascript代码复用模式
2015/01/28 Javascript
分享有关jQuery中animate、slide、fade等动画的连续触发、滞后反复执行的bug
2016/01/10 Javascript
jQuery基于toggle实现click触发DIV的显示与隐藏问题分析
2016/06/12 Javascript
jQuery AJAX timeout 超时问题详解
2016/06/21 Javascript
快速解决js动态改变dom元素属性后页面及时渲染的问题
2016/07/06 Javascript
jquery删除table当前行的实例代码
2016/10/07 Javascript
浅谈JS如何实现真正的对象常量
2017/06/25 Javascript
webpack使用 babel-loader 转换 ES6代码示例
2017/08/21 Javascript
动态加载权限管理模块中的Vue组件
2018/01/16 Javascript
前端vue+elementUI如何实现记住密码功能
2020/09/20 Javascript
js实现磁性吸附的示例
2020/10/26 Javascript
vue3.0 项目搭建和使用流程
2021/03/04 Vue.js
分享一个常用的Python模拟登陆类
2015/03/29 Python
Python新手在作用域方面经常容易碰到的问题
2015/04/03 Python
python3实现读取chrome浏览器cookie
2016/06/19 Python
python代码过长的换行方法
2018/07/19 Python
Python3利用Dlib实现摄像头实时人脸检测和平铺显示示例
2019/02/21 Python
Django 配置多站点多域名的实现步骤
2019/05/17 Python
如何在Python中实现goto语句的方法
2019/05/18 Python
使用Rasterio读取栅格数据的实例讲解
2019/11/26 Python
python matplotlib中的subplot函数使用详解
2020/01/19 Python
Python数据可视化处理库PyEcharts柱状图,饼图,线性图,词云图常用实例详解
2020/02/10 Python
Django Session和Cookie分别实现记住用户登录状态操作
2020/07/02 Python
python3爬虫中异步协程的用法
2020/07/10 Python
SmartBuyGlasses意大利:购买太阳镜、眼镜和隐形眼镜
2018/11/20 全球购物
英国豪华装饰照明品牌的在线零售商:Inspyer Lighting
2019/12/10 全球购物
女大学生毕业找工作的自我评价
2013/10/03 职场文书
总经理职责
2013/12/22 职场文书
青年文明号事迹材料
2014/01/18 职场文书
革命先烈的英雄事迹材料
2014/02/15 职场文书
倡议书格式
2014/04/14 职场文书
python playwright 自动等待和断言详解
2021/11/27 Python