一.准备环节
iscroll.js 5.x版本项目地址 https://github.com/cubiq/iscroll
演示地址:http://pnc.co.il/dev/iscroll-5-pull-to-refresh-and-infinite-demo.html
下载解压,我们打开demos目录,把click复制,改名字为app,也就是我们处理的基础,app文件目录下的index.html改为app.html,都是为了更好理解为自己创建的应用
我们打开app.html,先预览一下js文件,就是iscroll.js,看看就好,我们没必要去改,我们返回html页面,
js部分做出修改如下:
<script type="text/javascript"> window.onload=function(){ var myScroll; myScroll = new IScroll('#wrapper', { mouseWheel: true, click: true }); document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false); }; </script>
html的body标签调用的载入去掉,这样看着才舒心:
<body>
:::::最重要的一点,在引入类库的目录下我们可以看到很多iscroll.js的类库文件,我们选择下面的,这是事最全的,可以保证所有api被支持:
我们引入js部分代码改成如下:
<script type="text/javascript" src="../../build/iscroll-probe.js"></script>
我们需要找到针对iscroll的api,根据api提供的属性和方法等去修改目标效果。
二.接口使用和基本封装
----1.思考
我们要找到的是事件:
1.下拉事件接口
2.上拉事假接口
我们找到后,
针对下拉做提示刷新图标显示
针对上拉,就去ajax请求调用,当然我们只要模拟插入数据就好了。
针对5.x版本,我们一定要找到对应的api,不同版本的api是不同的,我们大致罗列iscroll5.x的所有api:
网上的一套总结:http://www.cnblogs.com/leolai/articles/4204345.html
官网虽好,英文水平不行:http://iscrolljs.com/
----2.事件:
myScroll.on('scrollStart', function(){console.log("拖拽开始")});
myScroll.on('scroll', function(){console.log("拖拽中")});
myScroll.on('scrollEnd', function(){console.log("拖拽结束")});
我们修改代码,加入事件测试:
<script type="text/javascript"> window.onload=function(){ var myScroll; myScroll = new IScroll('#wrapper', { mouseWheel: true, //是否监听鼠标滚轮事件 bounceTime:600, //弹力动画持续的毫秒数 probeType: 3 }); myScroll.on('scrollStart', function(){console.log("开始")}); myScroll.on('scroll', function(){console.log("拖拽中")}); myScroll.on('scrollEnd', function(){console.log("结束")}); document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false); //alert(myScroll.y) }; </script>
测试的日志显示,表示我们需要的事件被支持:
----3.属性
myScroll.x //当前位置
myScroll.y
myScroll.maxScrollX //当滚动到底部时的 myScroll.x/y
myScroll.maxScrollY
myScroll.directionX //上一次的滚动方向(-1 下/右, 0 保持原状, 1 上/左)
myScroll.directionY
myScroll.currentPage //当前Snap信息
我们的处理都是下拉和上拉处理,毫无疑问在y轴的处理才是我们需要的,我们需要的api属性大概应该如下:
myScroll.y //当前位置y
myScroll.maxScrollY //当滚动到底部时的 y
我们在 scroll 事件输出这两个信息测试,js代码修改如下:
<script type="text/javascript"> window.onload=function(){ var myScroll; myScroll = new IScroll('#wrapper', { mouseWheel: true, //是否监听鼠标滚轮事件 bounceTime:600, //弹力动画持续的毫秒数 probeType: 3 }); myScroll.on('scrollStart', function(){console.log("开始")}); myScroll.on('scroll', function(){ console.log("拖拽中y:"+myScroll.y); console.log("拖拽底部y:"+myScroll.maxScrollY); }); myScroll.on('scrollEnd', function(){console.log("结束")}); document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false); }; </script>
分析打印日志,我们得出myScroll.maxScrollY 是固定值;
myScroll.y是时时变化值;
我们结合实际:
下拉就是myScroll.y大于0;
下拉就是myScroll.y小于myScroll.maxScrollY ;
----4.根据y值做出最基本封装
根据上面的结果,我们做了下面判断处理,并日志打印,我们写个5的差值,就是为了避免一移动就触发
<script type="text/javascript"> window.onload=function(){ var myScroll; myScroll = new IScroll('#wrapper', { mouseWheel: true, //是否监听鼠标滚轮事件 bounceTime:600, //弹力动画持续的毫秒数 probeType: 3 }); myScroll.on('scrollStart', function(){console.log("开始")}); myScroll.on('scroll', function(){ if (this.y > 5) { //下拉刷新效果 console.log("下拉"); } else if (this.y < (this.maxScrollY - 5)) { //上拉刷新效果 console.log("上拉"); }; }); myScroll.on('scrollEnd', function(){console.log("结束")}); document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false); }; </script>
----5.二次封装处理
我们问题在哪里?拿下拉举例子,就是只要下拉就打印日志,这是不符合逻辑的,应该是
判断出下拉或者上拉 事件
在下拉或者上拉结束打印日志或者处理
我们删除开始事件,这个已经不用,
我们创建表示上拉和下拉的变量,然后在结束时间根据标志去做判断处理,代码修改如下:
<script type="text/javascript"> window.onload=function(){ var myScroll; myScroll = new IScroll('#wrapper', { mouseWheel: true, //是否监听鼠标滚轮事件 bounceTime:600, //弹力动画持续的毫秒数 probeType: 3 }); var handle=0;//初始为0,无状态;1表示下拉,2表示上拉 myScroll.on('scroll', function(){ if (this.y > 5) { //下拉刷新效果 ,标识设置为1 handle=1; } else if (this.y < (this.maxScrollY - 5)) { //上拉刷新效果 ,表示设置为2 handle=2; }; }); myScroll.on('scrollEnd', function(){ if(handle==1){ //下拉刷新处理 console.log("下拉"); myScroll.refresh(); handle=0;//重设为0,改为无状态 }else if(handle==2){ //上拉刷新处理 console.log("上拉"); handle=0;//重设为0,改为无状态 }else{handle=0;}; }); document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false); }; </script>
我们谷歌浏览器,去测试,就发现是没什么问题的,下拉/上拉+结束才会处理。
这样会显得结构比较乱,我们会好把处理的程序代码放在外面调用处理,我们进一步修改优化如下:
<script type="text/javascript"> window.onload=function(){ var myScroll; myScroll = new IScroll('#wrapper', { mouseWheel: true, //是否监听鼠标滚轮事件 bounceTime:600, //弹力动画持续的毫秒数 probeType: 3 }); var handle=0;//初始为0,无状态;1表示下拉,2表示上拉 myScroll.on('scroll', function(){ if (this.y > 5) {//下拉刷新效果 ,标识设置为1 handle=1; } else if (this.y < (this.maxScrollY - 5)) {//上拉刷新效果 ,表示设置为2 handle=2; }; }); myScroll.on('scrollEnd', function(){ if(handle==1){//下拉刷新处理 downrefresh() handle=0;//重设为0,改为无状态 }else if(handle==2){//上拉刷新处理 upajaxload() handle=0;//重设为0,改为无状态 }else{handle=0;}; }); document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false); function downrefresh(){//刷新处理 console.log("下拉"); myScroll.refresh(); }; function upajaxload(){//加载处理 console.log("上拉"); }; }; </script>
对于结束时的判断我们只要放在这两个函数里面就好了,下拉刷新和上拉加载的处理代码。
----6.三次封装处理
下拉就不必多说,app里面就是加载下面的数据,但是下拉的时候我们会看到提示内容:
下拉过程中,那个位置要显示些什么(提示啊),我们现在就在这个部分加上处理,其实上拉要是也有的话,原理一样。
我们在页面这个位置定位一个标签,写入要显示的内容,开始透明度为0,我们在下拉时改变透明度去显示
<script type="text/javascript"> window.onload=function(){ var requestf5=document.getElementById("requestf5"); var myScroll; myScroll = new IScroll('#wrapper', { mouseWheel: true, //是否监听鼠标滚轮事件 bounceTime:600, //弹力动画持续的毫秒数 probeType: 3 }); var handle=0;//初始为0,无状态;1表示下拉,2表示上拉 myScroll.on('scroll', function(){ if (this.y > 5) {//下拉刷新效果 ,标识设置为1 handle=1; if(this.y>20){ requestf5.style.opacity=1; }else{ requestf5.style.opacity=0; }; } else if (this.y < (this.maxScrollY - 5)) {//上拉刷新效果 ,表示设置为2 handle=2; }; }); myScroll.on('scrollEnd', function(){ if(handle==1){//下拉刷新处理 downrefresh() handle=0;//重设为0,改为无状态 }else if(handle==2){//上拉刷新处理 upajaxload() handle=0;//重设为0,改为无状态 }else{handle=0;}; }); document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false); function downrefresh(){//刷新处理 console.log("下拉"); myScroll.refresh(); }; function upajaxload(){//加载处理 console.log("上拉"); }; }; </script>
当时我的是非常粗糙的处理,这个提示根据你的设计可以丰富起来。
基本的处理和封装以及api的使用就结束了,还有很多参数的设置,可以参考api。
三.非常简单的模拟实例
刷新就这样就可以了,我们给下拉加入请求处理,就是ajax载入数据,我们修改页面结构,第一页内容默认显示,我们引入jq类库,方便我们ajax的模拟处理和节点插入
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0"> <title>iScroll demo: click</title> <script type="text/javascript" src="../../build/iscroll-probe.js"></script> <script type="text/javascript" src="jquery-1.10.2.js"></script> <script type="text/javascript"> $(function(){ var requestf5=document.getElementById("requestf5"); var myScroll; myScroll = new IScroll('#wrapper', { mouseWheel: true, //是否监听鼠标滚轮事件 bounceTime:600, //弹力动画持续的毫秒数 probeType: 3 }); var handle=0;//初始为0,无状态;1表示下拉,2表示上拉 myScroll.on('scroll', function(){ if (this.y > 5) {//下拉刷新效果 ,标识设置为1 handle=1; if(this.y>20){ requestf5.style.opacity=1; }else{ requestf5.style.opacity=0; }; } else if (this.y < (this.maxScrollY - 5)) {//上拉刷新效果 ,表示设置为2 handle=2; }; }); myScroll.on('scrollEnd', function(){ if(handle==1){//下拉刷新处理 downrefresh() handle=0;//重设为0,改为无状态 }else if(handle==2){//上拉刷新处理 upajaxload() handle=0;//重设为0,改为无状态 }else{handle=0;}; }); document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false); function downrefresh(){//刷新处理 console.log("下拉"); page=1; myScroll.refresh(); }; var page=1; var limit=10; var jsondata=[ {'aa':111,'bb':111111}, {'aa':222,'bb':111111}, {'aa':333,'bb':111111}, {'aa':444,'bb':111111}, {'aa':555,'bb':111111}, {'aa':666,'bb':111111}, {'aa':777,'bb':111111}, {'aa':888,'bb':111111}, {'aa':999,'bb':111111}, {'aa':123,'bb':111111}, {'aa':456,'bb':111111}, {'aa':789,'bb':111111}, {'aa':987,'bb':111111}, {'aa':654,'bb':111111}, {'aa':321,'bb':111111}, {'aa':556,'bb':111111}, {'aa':223,'bb':111111}, {'aa':112,'bb':111111}, {'aa':889,'bb':111111}, {'aa':778,'bb':111111}, {'aa':998,'bb':111111}, {'aa':447,'bb':111111}, {'aa':852,'bb':111111}, {'aa':741,'bb':111111}, {'aa':963,'bb':111111}, {'aa':369,'bb':111111}, {'aa':258,'bb':111111}, {'aa':147,'bb':111111}, {'aa':753,'bb':111111}, {'aa':159,'bb':111111}, {'aa':999999,'bb':999999999999}, {'aa':999,'bb':999999}, {'aa':9,'bb':999999999}, {'aa':99,'bb':999999999} ]; var isfirst=true; function upajaxload(){//加载处理 if(isfirst){ isfirst=false; setTimeout(function(){ page+=1; for(var i=(page-1)*limit;i<(page-1)*limit+limit;i++){ if(i<jsondata.length){ $(".demo").append('<div class="list"><p>'+jsondata[i].aa+'</p><p>'+jsondata[i].bb+'</p></div>'); }; }; myScroll.refresh();//刷新结构 isfirst=true; },1000); } }; }); </script> <style type="text/css"> * { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } html { -ms-touch-action: none; } *{ padding: 0; margin: 0; border: 0; } body { font-size: 12px; font-family: ubuntu, helvetica, arial; overflow: hidden; /* this is important to prevent the whole page to bounce */ } #header { position: absolute; z-index: 2; top: 0; left: 0; width: 100%; height: 45px; line-height: 45px; background: #CD235C; padding: 0; color: #eee; font-size: 20px; text-align: center; font-weight: bold; } #footer { position: absolute; z-index: 2; bottom: 0; left: 0; width: 100%; height: 48px; background: #444; padding: 0; border-top: 1px solid #444; } #wrapper { position: absolute; z-index: 1; top: 45px; bottom: 48px; left: 0; width: 100%; background: #ccc; overflow: hidden; } #scroller { position: absolute; z-index: 1; -webkit-tap-highlight-color: rgba(0,0,0,0); width: 100%; -webkit-transform: translateZ(0); -moz-transform: translateZ(0); -ms-transform: translateZ(0); -o-transform: translateZ(0); transform: translateZ(0); -webkit-touch-callout: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; -webkit-text-size-adjust: none; -moz-text-size-adjust: none; -ms-text-size-adjust: none; -o-text-size-adjust: none; text-size-adjust: none; } #requestf5{position:absolute; width:100px; height:20px; line-height:20px; text-align:center; left:50%; margin-left:-50px; top:45px; z-index:2; opacity:0;} .demo{ background:#FFF;} .demo .list{ height:200px;} </style> </head> <body> <div id="header">iScroll</div> <div id="requestf5">请求刷新</div> <div id="wrapper"> <div id="scroller"> <div class="demo"> <div class="list"> <p>1</p> <p>1111111</p> </div> <div class="list"> <p>2</p> <p>222222</p> </div> <div class="list"> <p>1</p> <p>333333</p> </div> <div class="list"> <p>1</p> <p>444444444</p> </div> <div class="list"> <p>1</p> <p>5555555555</p> </div> <div class="list"> <p>1</p> <p>666666666666</p> </div> <div class="list"> <p>1</p> <p>777777777</p> </div> <div class="list"> <p>1</p> <p>888888888</p> </div> <div class="list"> <p>1</p> <p>9998999</p> </div> <div class="list"> <p>1</p> <p>9999999999999999</p> </div> </div> </div> </div> <div id="footer"></div> </body> </html>
非常粗糙的基本结构就出来了!下拉显示刷新操作,其实应该清空重新载入,我没有去模拟
同样显示的刷新提示还可以做非常细致的修饰,我们是可以获取上一步的y值得,与当前值比较,我们在回弹的时候还可以二次修饰变化
上拉提示同下拉添加
同样在显示加载数据的时候我们可以利用css3的处理显示
四.非常简单的模拟实例下载
http://www.oschina.net/code/snippet_2352644_51591