JS+CSS实现移动端下拉刷新

闲来无事,写了一个当下比较常见的下拉刷新/上拉加载的jquery插件,代码记录在这里,有兴趣将代码写成插件与npm包可以留言。

体验地址:http://owenliang.github.io/pullToRefresh/

项目地址:https://github.com/owenliang/pullToRefresh

实现注意:

  • 利用transition做动画时,优先使用transform:translate取代top,后者动画流畅度存在问题。
  • 各移动浏览器对手势触摸的处理不同(简单罗列如下),但是下面的应对方案又会导致部分浏览器的overflow:scroll失效,总之难以兼容:
    • 微信浏览器下拉自带回弹动画:可以禁止document的touchmove事件默认处理行为。
    • 谷歌浏览器下拉自带刷新功能:利用属性touch-action: none可以禁掉。
  • 针对上述问题,我的建议是滚动一律用iscroll5插件模拟实现(非overflow:scroll),然后利用上面的方法禁掉浏览器的默认touchmove行为。
  • transition如果有多个属性,那么transitionend回调会为每个属性回调一次,因此遇到其中任意一个回调就应该把css和transitionend回调都删除掉。
  • 浏览器在执行JS代码时没有机会重绘UI,因此在使用transition的时候一定要注意把修改动画终止CSS的代码通过setTimeout延迟一会执行。
  • 元素想垂直居中可以用position:absolute,然后通过top:0,bottom:0,margin:auto实现,相当于给绝对定位元素外面套了一个虚拟的父容器,top=0,bottom=0相当于父容器的尺寸。
  • 动画方面利用transform的3D动画,可以触发浏览器使用硬件(GPU)加速,比如:使用transform:rotateZ,这样动画效果更流畅。
  • 为了实现多点触摸,踩了半天的坑:
    • 一开始希望在touchstart和touchend/touchcancel里通过changedTouches来追踪维护当前正在触屏的手指信息,经过真机调试日志发现ios和android都在复杂高频的多指操作情况下,部分手指的离开信息并没有通过changedtouches通知,简直坑死了。
    • 为了克服这个问题,在touchstart里和touchend里总是与targetTouches进行全量的diff,因为targetTouches是当前正在触摸指定区域的手指列表,它是很准确的(比changedtouches这个增量的实现要靠谱的多),diff代码如下:

  • 一定要处理touchcancel,当你正在触摸时如果来电话,或者把浏览器切换到后台,或者手指移动到了浏览器窗口外都有可能触发这个事件,如果发生这个事件那么touchend就不会触发了,因此写逻辑的时候直接把它俩视为等价即可。

 

如果文章帮助您解决了工作难题,您可以帮我点击屏幕上的任意广告,或者赞助少量费用来支持我的持续创作,谢谢~