微信小程序实现瀑布流布局与无限加载的方法详解


Posted in Javascript onMay 12, 2017

前言

瀑布流布局是一种比较流行的页面布局方式,最典型的就是Pinterest.com,每个卡片的高度不都一样,形成一种参差不齐的美感。

在HTML5中,我们可以找到很多基于jQuery之类实现的瀑布流布局插件,轻松做出这样的布局形式。在微信小程序中,我们也可以做出这样的效果,不过由于小程序框架的一些特性,在实现思路上还是有一些差别的。

今天我们就来看一下如何在小程序中去实现这种瀑布流布局:

微信小程序实现瀑布流布局与无限加载的方法详解
小程序瀑布流布局

我们要实现的是一个固定2列的布局,然后将图片数据动态加载进这两列中(而加载进来的图片,会根据图片实际的尺寸,来决定到底是放在左列还是右列中)。

/* 单个图片容器的样式 */
.img_item {
 width: 48%;
 margin: 1%;
 display: inline-block;
 vertical-align: top;
}

我们知道,在HTML中,我们要动态加载图片的话,通常会使用new Image()创建一个图片对象,然后通过它来动态加载一个url指向的图片,并获取图片的实际尺寸等信息。而在小程序框架中,并没有提供相应的JS对象来处理图片加载。其实我们可以借助wxml中的<image>组件来完成这样的功能,虽然有点绕,但还是能满足我们的功能要求的。

<!-- 在页面上放一个隐藏区域,并用image组件去加载一个或多个图片资源 -->
<view style="display:none">
 <image wx:for="{{images}}" wx:key="id" id="{{item.id}}" src="{{item.pic}}" bindload="onImageLoad"></image>
</view>

我们可以在Page中通过数据绑定,来传递要加载的图片信息到wxml中,让<image>组件去加载图片资源,然后当图片加载完成的时候,通过bindload指定的事件处理函数来做进一步处理。

我们来看一下Page文件中定义的onImageLoad函数。在其中,我们可以从传入的事件对象e上,获取到<image>组件的丰富信息,包括通过它加载进来的图片的实际大小。然后我们将图片按照页面上实际需要显示的尺寸,计算出同比例缩放后的尺寸。接着,我们可以根据左右两列目前累积的内容高度,来决定把当前加载进来的图片放到哪一边。

let col1H = 0;
let col2H = 0;

Page({

 data: {
  scrollH: 0,
  imgWidth: 0,
  loadingCount: 0,
  images: [],
  col1: [],
  col2: []
 },

 onLoad: function () {
  wx.getSystemInfo({
   success: (res) => {
    let ww = res.windowWidth;
    let wh = res.windowHeight;
    let imgWidth = ww * 0.48;
    let scrollH = wh;

    this.setData({
     scrollH: scrollH,
     imgWidth: imgWidth
    });

    //加载首组图片
    this.loadImages();
   }
  })
 },

 onImageLoad: function (e) {
  let imageId = e.currentTarget.id;
  let oImgW = e.detail.width;   //图片原始宽度
  let oImgH = e.detail.height;  //图片原始高度
  let imgWidth = this.data.imgWidth; //图片设置的宽度
  let scale = imgWidth / oImgW;  //比例计算
  let imgHeight = oImgH * scale;  //自适应高度

  let images = this.data.images;
  let imageObj = null;

  for (let i = 0; i < images.length; i++) {
   let img = images[i];
   if (img.id === imageId) {
    imageObj = img;
    break;
   }
  }

  imageObj.height = imgHeight;

  let loadingCount = this.data.loadingCount - 1;
  let col1 = this.data.col1;
  let col2 = this.data.col2;

  //判断当前图片添加到左列还是右列
  if (col1H <= col2H) {
   col1H += imgHeight;
   col1.push(imageObj);
  } else {
   col2H += imgHeight;
   col2.push(imageObj);
  }

  let data = {
   loadingCount: loadingCount,
   col1: col1,
   col2: col2
  };

  //当前这组图片已加载完毕,则清空图片临时加载区域的内容
  if (!loadingCount) {
   data.images = [];
  }

  this.setData(data);
 },

 loadImages: function () {
  let images = [
   { pic: "../../images/1.png", height: 0 },
   { pic: "../../images/2.png", height: 0 },
   { pic: "../../images/3.png", height: 0 },
   { pic: "../../images/4.png", height: 0 },
   { pic: "../../images/5.png", height: 0 },
   { pic: "../../images/6.png", height: 0 },
   { pic: "../../images/7.png", height: 0 },
   { pic: "../../images/8.png", height: 0 },
   { pic: "../../images/9.png", height: 0 },
   { pic: "../../images/10.png", height: 0 },
   { pic: "../../images/11.png", height: 0 },
   { pic: "../../images/12.png", height: 0 },
   { pic: "../../images/13.png", height: 0 },
   { pic: "../../images/14.png", height: 0 }
  ];

  let baseId = "img-" + (+new Date());

  for (let i = 0; i < images.length; i++) {
   images[i].id = baseId + "-" + i;
  }

  this.setData({
   loadingCount: images.length,
   images: images
  });
 }

})

这里是显示在两列图片的wxml代码,我们可以看到在<scroll-view>组件上,我们通过使用bindscrolltolower设置了事件监听函数,当滚动到底部的时候,会触发loadImages去再加载下一组的图片数据,这样就形成了无限的加载:

<scroll-view scroll-y="true" style="height:{{scrollH}}px" bindscrolltolower="loadImages">
 <view style="width:100%">
 <view class="img_item">
  <view wx:for="{{col1}}" wx:key="id">
  <image src="{{item.pic}}" style="width:100%;height:{{item.height}}px"></image>
  </view>
 </view>
 <view class="img_item">
  <view wx:for="{{col2}}" wx:key="id">
  <image src="{{item.pic}}" style="width:100%;height:{{item.height}}px"></image>
  </view>
 </view>
 </view>
</scroll-view>

好了,挺简单的一个例子,如果你有更好的方法,不吝分享一下哦。

完整代码可以在Github下载:https://github.com/zarknight/wx-falls-layout  也可以通过本地进行下载

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
用javascript实现读取txt文档的脚本
Jul 20 Javascript
jquery阻止冒泡事件使用模拟事件
Sep 06 Javascript
Js Jquery创建一个弹出层可加载一个页面
May 08 Javascript
angularJS 中input示例分享
Feb 09 Javascript
JavaScript学习笔记整理_setTimeout的应用
Sep 19 Javascript
js实现的光标位置工具函数示例
Oct 03 Javascript
jQuery内存泄露解决办法
Dec 13 Javascript
Vue.js上下滚动加载组件的实例代码
Jul 17 Javascript
BootStrap Table实现server分页序号连续显示功能(当前页从上一页的结束序号开始)
Sep 12 Javascript
js实现手机web图片左右滑动效果
Dec 29 Javascript
浅谈webpack 构建性能优化策略小结
Jun 13 Javascript
vue-cli3+typescript新建一个项目的思路分析
Aug 06 Javascript
WebSocket实现简单客服聊天系统
May 12 #Javascript
vue2.0结合Element实现select动态控制input禁用实例
May 12 #Javascript
详解微信小程序 相对定位和绝对定位
May 11 #Javascript
Vue通过input筛选数据
Oct 26 #Javascript
微信小程序 action-sheet 反馈上拉菜单简单实例
May 11 #Javascript
jQuery遮罩层实例讲解
May 11 #jQuery
在JS中如何把毫秒转换成规定的日期时间格式实例
May 11 #Javascript
You might like
PHP+MYSQL的文章管理系统(二)
2006/10/09 PHP
详解php的魔术方法__get()和__set()使用介绍
2012/09/19 PHP
PHP实现简单爬虫的方法
2015/07/29 PHP
PHP生成随机密码4种方法及性能对比
2020/12/11 PHP
比较简单实用的使用正则三种版本的js去空格处理方法
2007/11/18 Javascript
JavaScript入门之事件、cookie、定时等
2011/10/21 Javascript
Jvascript学习实践案例(开发常用)
2012/06/25 Javascript
js中的数组Array定义与sort方法使用示例
2013/08/29 Javascript
js(jQuery)获取时间的方法及常用时间类搜集
2013/10/23 Javascript
在AngularJS应用中实现一些动画效果的代码
2015/06/18 Javascript
学习掌握JavaScript中this的使用技巧
2016/08/29 Javascript
JavaScript自定义函数实现查找两个字符串最长公共子串的方法
2016/11/24 Javascript
angularJs使用$watch和$filter过滤器制作搜索筛选实例
2017/06/01 Javascript
浅谈关于.vue文件中style的scoped属性
2017/08/19 Javascript
vue-router相关基础知识及工作原理
2018/03/16 Javascript
vue中rem的配置的方法示例
2018/08/30 Javascript
layui监听单元格编辑前后交互的例子
2019/09/16 Javascript
JQuery中DOM节点的操作与访问方法实例分析
2019/12/23 jQuery
[47:42]Fnatic vs Liquid 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
Python、PyCharm安装及使用方法(Mac版)详解
2017/04/28 Python
python如何读写csv数据
2018/03/21 Python
Python操作mongodb数据库进行模糊查询操作示例
2018/06/09 Python
Python中的None与 NULL(即空字符)的区别详解
2020/09/24 Python
使用 css3 transform 属性来变换背景图的方法
2019/05/07 HTML / CSS
Crabtree & Evelyn英国官网:瑰珀翠护手霜、香水、沐浴和身体护理
2018/04/26 全球购物
银行实习人员自我鉴定
2013/09/22 职场文书
教育科研先进个人材料
2014/01/26 职场文书
项目申报专员岗位职责
2014/07/09 职场文书
防邪知识进家庭活动方案
2014/08/26 职场文书
2014年小学语文工作总结
2014/12/20 职场文书
年度考核登记表个人总结
2015/03/06 职场文书
考勤制度通知
2015/04/25 职场文书
运动会闭幕式主持词
2015/07/01 职场文书
Pycharm 如何设置HTML文件自动补全代码或标签
2021/05/21 Python
一文搞懂redux在react中的初步用法
2021/06/09 Javascript
浅谈Python响应式类库RxPy
2021/06/14 Python