AutoCAD 3DMAX C语言 Pro/E UG JAVA编程 PHP编程 Maya动画 Matlab应用 Android
Photoshop Word Excel flash VB编程 VC编程 Coreldraw SolidWorks A Designer Unity3D
 首页 > JavaScript

JS+CSS实现下拉刷新/上拉加载插件

51自学网 http://www.51zixue.net
js,下拉刷新上拉加载插件,下拉刷新上拉加载

闲来无事,写了一个当下比较常见的下拉刷新/上拉加载的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延迟一会执行。

贴代码上首页,欢迎留言交流,需一位有兴趣有时间的朋友合作,主要做2件事:

1)插件改为NPM包。

2)基于pullToRefresh库,开发类似"今日头条"的左右滑动UI。

pullToRefresh.js:

/** * 为指定的容器添加滚动条,支持下拉刷新与上拉加载功能 * @param container 需要滚动的容器,要求设置css: position!=static,height= * @param option 配置项,详见下方defaultOption说明 * @return 返回对象用于操控此区域,当前暴露了iscroll的refresh函数,当你在插件之外向滚动区域增加/删除内容后应该主动调用一次 * @description * * 2017-03-29 * 1)支持上拉加载 * 2017-03-30 * 1)改为jquery静态函数插件 * 2)支持关闭下拉刷新或上拉加载 */$.installPullToRefresh =function (container, option) {  // 起始触摸位置  var touchStartY = 0;  // 起始图标位置  var pullStartY = 0;  // 当前的触摸事件  var touchEvent = null;  // 当前的刷新事件  var refreshEvent = null;  // 当前图标位置  var curY = -55;  // 当前的加载事件  var loadEvent = null;  // 默认参数  var defaultOption = {    // 刷新相关    noRefresh: false, // 关闭下拉刷新特性    pauseBound: 40, // 触发刷新的位置(也是图标loading暂停的位置)    lowerBound: 80, // 最大下拉到多少px    loadImg: "load.png", // loading图片    pullImg: "pull.png", // 下拉图片    onRefresh: function (refreshDone) { // 刷新数据回调      setTimeout(function() { // 默认不做任何事        refreshDone();      }, 0);    },    // 加载相关    noLoad: false, // 关闭上拉加载特性    bottomHeight: 1, // 距离滚动条底部多少px发起刷新    onLoad: function (loadDone) {      setTimeout(function() {        loadDone();      }, 0);    },  };  var finalOption = $.extend(true, defaultOption, option);  // 创建iscroll5滚动区域  var iscroll = new IScroll(container, {    bounce: false,  });  // 关闭上拉加载特性  if (!finalOption.noLoad) {    // 监听滚动结束事件,用于上拉加载    iscroll.on('scrollEnd', function () {      // 有滚动条的情况下,才允许上拉加载      if (iscroll.maxScrollY < 0) { // maxScrollY<0表明出现了滚动条        var bottomDistance = (iscroll.maxScrollY - iscroll.y) * -1;        // 距离底部足够近,触发加载        if (bottomDistance <= finalOption.bottomHeight) {          // 当前没有刷新和加载事件正在执行          if (!loadEvent && !refreshEvent) {            loadEvent = {}; // 生成新的加载事件            finalOption.onLoad(function (error, msg) {              loadEvent = null; // 清理当前的加载事件              // 延迟重绘滚动条              setTimeout(function () {                iscroll.refresh();              }, 0);            });          }        }      }    });  }  // 关闭下拉刷新特性  if (!finalOption.noRefresh) {    // 紧邻滚动区域,容纳刷新图标    var pullContainer = $('<div class="pullContainer"></div>')    // 创建小图标    var pullToRefresh = $('<div class="pullToRefresh"><img src="' + finalOption.pullImg + '"></div>');    // 保留小图标的快捷方式    var pullImg = pullToRefresh.find("img");    // 小图标加入到容器    pullContainer.append(pullToRefresh);    // 小图标容器添加到滚动区域之前    $(container).before(pullContainer);    // 预加载loadImg    $('<img src="' + finalOption.loadImg + '">');    // 设置transform的函数    function cssTransform(node, content) {      node.css({        '-webkit-transform' : content,        '-moz-transform'  : content,        '-ms-transform'   : content,        '-o-transform'   : content,        'transform'     : content,      });    }    // 调整小图标位置,角度,透明度    function goTowards(translateY, rotate, opcaticy) {      // 更新当前小图标的位置,获取css(transform)比较麻烦,所以每次变更时自己保存      curY = translateY;      // 旋转图标(根据抵达lowerBound的比例旋转,最大转1圈)      if (rotate === undefined) {        rotate = (curY / finalOption.lowerBound) * 360;      }      // 透明度根据抵达pauseBound的比例计算      if (opcaticy === undefined) {        opcaticy = (curY / finalOption.pauseBound) * 1;        if (opcaticy > 1) {          opcaticy = 1;        }      }      // 改变位置和旋转角度      cssTransform(pullToRefresh, "translateY(" + translateY + "px) translateZ(0)" + "rotateZ(" + rotate + "deg)");      // 改变透明度      pullToRefresh.css("opacity", opcaticy);    }    // 开启回弹动画    function tryStartBackTranTop() {      // 启动回弹动画      pullToRefresh.addClass("backTranTop");      // 判断是否触发刷新      if (curY >= finalOption.pauseBound) {        goTowards(finalOption.pauseBound);        // 回弹动画结束发起刷新        pullToRefresh.on('transitionend webkitTransitionEnd oTransitionEnd', function (event) {          // 由于transitionend会对每个属性回调一次,所以只处理其中一个          if (event.originalEvent.propertyName == "transform") {            // 暂停动画            pullToRefresh.removeClass("backTranTop");            pullToRefresh.unbind();            // 透明度重置为1            goTowards(finalOption.pauseBound, undefined, 1);            // 切换图片为loading图            pullImg.attr("src", finalOption.loadImg);            // 因为anamition会覆盖transform的原因,使用top临时定位元素            pullToRefresh.addClass("loadingAnimation");            pullToRefresh.css("top", finalOption.pauseBound + "px");            // 回调刷新数据,最终应将refreshEvent传回校验            finalOption.onRefresh(function (error, msg) {              // 用户回调时DOM通常已经更新, 需要通知iscroll调整(官方建议延迟执行,涉及到浏览器重绘问题)              setTimeout(function () {                iscroll.refresh();              }, 0);              // 重置角度,切换为pull图              goTowards(finalOption.pauseBound);              // 取消animation,重置top              pullToRefresh.removeClass("loadingAnimation");              pullToRefresh.css("top", "");              // 延迟过渡动画100毫秒,给浏览器重绘的机会              setTimeout(function () {                // 切换为pull图                pullImg.attr("src", finalOption.pullImg);                // 恢复动画                pullToRefresh.addClass("backTranTop");                // 刷新完成                refreshEvent = null;                // 弹回顶部                goTowards(-55);              }, 100);            });          }        });      } else {        goTowards(-55); // 弹回顶部        refreshEvent = null; // 未达成刷新触发条件      }    }    // 父容器注册下拉事件    $(container).on("touchstart", function (event) {      // 新的触摸事件      touchEvent = {};      // 有一个刷新事件正在进行      if (refreshEvent) {        return;      }      // 只有滚动轴位置接近顶部, 才可以生成新的刷新事件      if (iscroll.y < -1 * finalOption.lowerBound) {        return;      }      // 一个新的刷新事件      refreshEvent = touchEvent;      touchStartY = event.originalEvent.changedTouches[0].clientY;      pullStartY = curY;      // 如果存在,则关闭回弹动画与相关监听      pullToRefresh.removeClass("backTranTop");      pullToRefresh.unbind();      // 切换为pull图      pullImg.attr("src", finalOption.pullImg);    }).on("touchmove", function (event) {      // 在刷新未完成前触摸,将被忽略      if (touchEvent != refreshEvent) {        return;      }      var touchCurY = event.originalEvent.changedTouches[0].clientY;      var touchDistance = touchCurY - touchStartY; // 本次移动的距离      var curPullY = pullStartY + touchDistance; // 计算图标应该移动到的位置      // 向下不能拉出范围      if (curPullY > finalOption.lowerBound) {        curPullY = finalOption.lowerBound;      }      // 向上不能拉出范围      if (curPullY <= -55) {        curPullY = -55;      }      // 更新图标的位置      goTowards(curPullY);    }).on("touchend", function (event) {      // 在刷新未完成前触摸,将被忽略      if (touchEvent != refreshEvent) {        return;      }      // 尝试启动回弹动画      tryStartBackTranTop();    });  }  // 初始化iscroll  setTimeout(function() {    iscroll.refresh();  }, 0);  // 返回操作此区域的工具对象  return {    // 用户如果在下拉刷新之外修改了滚动区域的内容,需要主动调用refresh    refresh: function() {      // 延迟以便配合浏览器重绘      setTimeout(function() {        iscroll.refresh();      }, 0);    },    // 触发下拉刷新    triggerPull: function() {      // 正在刷新或者禁止刷新      if (refreshEvent || finalOption.noRefresh) {        return false;      }      // 暂停可能正在进行的最终阶段回弹动画      pullToRefresh.removeClass("backTranTop");      // 小图标移动到lowerbound位置      goTowards(finalOption.lowerBound);      // 创建新的刷新事件,占坑可以阻止在setTimeout之前的触摸引起刷新      refreshEvent = {};      // 延迟到浏览器重绘      setTimeout(function() {        tryStartBackTranTop();      }, 100);    },  };};Contact GitHub API Training Shop Blog About© 2017 GitHub, Inc. Terms Privacy Security Status Help

pullToRefresh.css:

.pullToRefresh {  position:absolute;  left:0;  right:0;  margin:auto;  width: 50px;  height: 50px;  z-index: 10;  opacity: 1;  transform:translateY(-55px) translateZ(0) rotateZ(0deg);  -ms-transform:translateY(-55px) translateZ(0) rotateZ(0deg);   /* IE 9 */  -moz-transform:translateY(-55px) translateZ(0) rotateZ(0deg);   /* Firefox */  -webkit-transform:translateY(-55px) translateZ(0) rotateZ(0deg); /* Safari 和 Chrome */  -o-transform:translateY(-55px) translateZ(0) rotateZ(0deg);   /* Opera */}.backTranTop{  transition: transform 0.8s ease, opacity 0.8s ease;  -moz-transition: transform 0.8s ease, opacity 0.8s ease; /* Firefox 4 */  -webkit-transition: transform 0.8s ease, opacity 0.8s ease; /* Safari 和 Chrome */  -o-transition: transform 0.8s ease, opacity 0.8s ease; /* Opera */}.pullContainer {  position:relative;}.pullToRefresh img {  display:block;  width: 40px;  height: 40px;  /* 让img居中在.pullToRefresh中 */  position: absolute;  top: 0;  bottom: 0;  left:0;  right:0;  margin:auto;}/* loading旋转动画 */.loadingAnimation{  animation: loadingFrame 1s infinite;  -moz-animation: loadingFrame 1s infinite;  /* Firefox */  -webkit-animation: loadingFrame 1s infinite;  /* Safari 和 Chrome */  -o-animation: loadingFrame 1s infinite;  /* Opera */}@keyframes loadingFrame{  from {    transform: rotateZ(360deg);  }  to {    transform: rotateZ(0deg);  }}@-moz-keyframes loadingFrame /* Firefox */{  from {    transform: rotateZ(360deg);  }  to {    transform: rotateZ(0deg);  }}@-webkit-keyframes loadingFrame /* Safari 和 Chrome */{  from {    transform: rotateZ(360deg);  }  to {    transform: rotateZ(0deg);  }}@-o-keyframes loadingFrame /* Opera */{  from {    transform: rotateZ(360deg);  }  to {    transform: rotateZ(0deg);  }}

以上所述是小编给大家介绍的JS+CSS实现下拉刷新/上拉加载插件,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对51zixue.net网站的支持!


js,下拉刷新上拉加载插件,下拉刷新上拉加载  
上一篇:JS正则获取HTML元素的方法  下一篇:ES6中Generator与异步操作实例分析