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


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 相关文章推荐
js隐藏与显示回到顶部按钮及window.onscroll事件应用
Jan 25 Javascript
jquery中常用的SET和GET$(”#msg”).html循环介绍
Oct 09 Javascript
如何学习Javascript入门指导
Nov 01 Javascript
jquery中的$(document).ready()使用小结
Feb 14 Javascript
JS操作COOKIE实现备忘记录的方法
Apr 01 Javascript
微信小程序 本地数据读取实例
Apr 27 Javascript
vue2.0s中eventBus实现兄弟组件通信的示例代码
Oct 25 Javascript
elementui的默认样式修改方法
Feb 23 Javascript
mpvue构建小程序的方法(步骤+地址)
May 22 Javascript
js计算最大公约数和最小公倍数代码实例
Sep 11 Javascript
Vue v-text指令简单使用方法示例
Sep 19 Javascript
如何利用node.js开发一个生成逐帧动画的小工具
Dec 01 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函数学习之PHP函数点评
2012/07/05 PHP
php获取本周开始日期和结束日期的方法
2015/03/09 PHP
php检测文本的编码
2015/07/26 PHP
php查找字符串中第一个非0的位置截取
2017/02/27 PHP
php中输出json对象的值(实现方法)
2018/03/07 PHP
JQuery中html()方法使用不当带来的陷阱
2011/04/07 Javascript
javascript向后台传送相同属性的参数即数组参数
2014/02/17 Javascript
页面加载完毕后滚动条自动滚动一定位置
2014/02/20 Javascript
Angularjs中的事件广播 —全面解析$broadcast,$emit,$on
2016/05/17 Javascript
BootstrapValidator不触发校验的实现代码
2016/09/28 Javascript
jQuery学习笔记——jqGrid的使用记录(实现分页、搜索功能)
2016/11/09 Javascript
canvas 画布在主流浏览器中的尺寸限制详细介绍
2016/12/15 Javascript
ES6教程之for循环和Map,Set用法分析
2017/04/10 Javascript
ES6 javascript中Class类继承用法实例详解
2017/10/30 Javascript
js统计页面上每个标签的数量实例代码
2018/05/29 Javascript
angularjs $http调用接口的方式详解
2018/08/13 Javascript
对vuejs的v-for遍历、v-bind动态改变值、v-if进行判断的实例讲解
2018/08/27 Javascript
JS 音频可视化插件Wavesurfer.js的使用教程
2018/10/31 Javascript
vue实现文字横向无缝走马灯组件效果的实例代码
2019/04/09 Javascript
稍微学一下Vue的数据响应式(Vue2及Vue3区别)
2019/11/21 Javascript
原生js实现瀑布流效果
2020/03/09 Javascript
JavaScript实现商品评价五星好评
2020/11/30 Javascript
Pycharm 文件更改目录后,执行路径未更新的解决方法
2019/07/19 Python
HTML5 Canvas 实现K线图的示例代码
2019/12/23 HTML / CSS
简洁的英文求职信范文
2014/05/03 职场文书
社区先进事迹材料
2014/05/19 职场文书
完美的中文自荐信
2014/05/24 职场文书
委托书怎么写
2014/07/31 职场文书
模范教师事迹材料
2014/12/16 职场文书
2015大学生求职信范文
2015/03/20 职场文书
早上好问候语大全
2015/11/10 职场文书
互联网创业商业模式以及赚钱法则有哪些?
2019/10/12 职场文书
golang中的并发和并行
2021/05/08 Golang
Mysql外键约束的创建与删除的使用
2022/03/03 MySQL
Redis高可用集群redis-cluster详解
2022/03/20 Redis
如何通过cmd 连接阿里云服务器
2022/04/18 Servers