H5基於iScroll實現下拉刷新,上拉加載更多....


1、初識iScroll 
最新版本已經更新到5.0,官網: http://cubiq.org/iscroll-5
iScroll 4 這個版本完全重寫了iScroll這個框架的原始代碼。這個項目的產生完全是因為移動版webkit瀏覽器(諸如iPhone,iPad,Android 這些系統上廣泛使用)提供了一種本地化的方式來對一個限定了高度和寬度的元素的內容進行滑動。
很不幸的是,這種情況下所有的web應用的頁面就不能夠包含具有position:absolute的頭、頁尾或者是一個內容可滾動的中間區域。
然而,Android系統最新修訂版已經可以支持這種功能了(盡管支持的力度還不是特別好),Apple公司似乎不太情願將one-finger滑動事件運用到div元素上。
除了以前版本的iScroll的特性以外,iScroll 4還包括如下的特性:
     (1)縮放(Pinch/Zoom)
    (2)拉動刷新(Pull up/down to refresh)
    (3)速度和性能提升
    (4)精確捕捉元素
    (5)自定義滾動條

2、使用技巧

      2.1、引用iScroll.js和index.js

<script src="./js/iscroll.js"></script>
<script src="./js/index.js"></script>

 iscroll.js為下拉刷新原生文件;

 index.js為自己整理的頁面腳本文件,用於初始化iScroll對象,在初始化時添加兩個事件監聽:touchMove、DOMContentLoaded。

      2.2、搭建HTML主體 結構,如下代碼:

<div id="wrapper"> 
   <ul>
      <li></li> ..... 
   </ul> 
</div>

注意事項: 運動的對象就是你ID  為wrapper下的第一個子元素。只有wrapper里的第一個子元素才可以滾動,如果你想要更多的元素可以滾動,那么你可以試試下面的這種寫法:

<div id="wrapper"> 
    <div id="scroller">
        <ul> <li></li> ... </ul> 
        <ul> <li></li> ... </ul>
    </div>
</div>

2.3、實現iScroll插件的onScrollEnd事件, 也就是在這個事件里調用你自己的ajax方法實現數據的刷新和追加。

onScrollEnd: function () {
      if (pullDownEl.className.match('flip')) {
                console.log(12);
                pullDownEl.className = 'loading';
                pullDownEl.querySelector('.pullDownLabel').innerHTML = '加載中...';                
                pullDownAction();    // Execute custom function (ajax call?)
       } else if (pullUpEl.className.match('flip')) {
                console.log(13);
                pullUpEl.className = 'loading';
                pullUpEl.querySelector('.pullUpLabel').innerHTML = '加載中...';                
                pullUpAction();    // Execute custom function (ajax call?)
      }
}

  2.4、上拉加載更多請求后台時就相當於分頁請求數據,這時候需要在ajax請求時發送pageIndex參數,而初始化加載時需要從后台返回一個pageCount以便前台判斷。

  2.5、最關鍵的就是實現下拉刷新方法(pullDownAction)和上拉加載更多(pullUpAction)方法。

 

3、效果圖:

4、代碼分析【index.js】

var myScroll,
    pullDownEl, pullDownOffset,
    pullUpEl, pullUpOffset,
    generatedCount = 0;

//pullDownAction方法用於模擬下拉刷新成功后,向頂端追加數據;
function pullDownAction () {
    setTimeout(function () {    
        var el, li, i;
        el = document.getElementById('thelist');

        for (i=0; i<3; i++) {
            console.log("generatedCount:"+generatedCount);
            li = document.createElement('li');
            li.innerText = 'Generated row ' + (++generatedCount);
            el.insertBefore(li, el.childNodes[0]);
        }
        myScroll.refresh();        //數據加載完成后,調用界面更新方法 
    }, 1000);    // <-- Simulate network congestion, remove setTimeout from production!
}

//pullDownAction方法用於模擬上拉刷新成功后,向底端追加數據;
function pullUpAction () {
    setTimeout(function () {    // <-- Simulate network congestion, remove setTimeout from production!
        var el, li, i;
        el = document.getElementById('thelist');

        for (i=0; i<3; i++) {
            li = document.createElement('li');
            li.innerText = 'Generated row ' + (++generatedCount);
            el.appendChild(li, el.childNodes[0]);
        }
        
        myScroll.refresh();        // Remember to refresh when contents are loaded (ie: on ajax completion)
    }, 1000);    // <-- Simulate network congestion, remove setTimeout from production!
}

/*初始化iScroll控件*/
function loaded() {
    pullDownEl = document.getElementById('pullDown');
    pullDownOffset = pullDownEl.offsetHeight;//表示獲取元素自身的高度
    pullUpEl = document.getElementById('pullUp');    
    pullUpOffset = pullUpEl.offsetHeight;
    
    myScroll = new iScroll('wrapper', {
        useTransition: true,   //表示是否使用css3中的過渡效果,默認為true;
        topOffset: pullDownOffset,//pullDown區間高度
        hScrollbar:false, //false隱藏水平方向上的滾動條
        vScrollbar:false// false 隱藏垂直方向上的滾動條
        onRefresh: function () {  //刷新方法
            if (pullDownEl.className.match('loading')) {
                console.log(19);
                pullDownEl.className = '';
                pullDownEl.querySelector('.pullDownLabel').innerHTML = '下拉刷新...';
            } else if (pullUpEl.className.match('loading')) {
                console.log(18);
                pullUpEl.className = '';
                pullUpEl.querySelector('.pullUpLabel').innerHTML = '上拉加載更多...';
            }
        },
        //onScrollMove:主要表示根據用戶下拉或上拉刷新的高度值,來顯示不同的交互文字;
        onScrollMove: function () {  //手指觸摸事件
            //this.y:表示手指下拉的高度
            if (this.y > 5 && !pullDownEl.className.match('flip')) {
                console.log(14);
                pullDownEl.className = 'flip';
                pullDownEl.querySelector('.pullDownLabel').innerHTML = '松手開始更新...';
                this.minScrollY = 0;
            } else if (this.y < 5 && pullDownEl.className.match('flip')) {
                console.log(15);
                pullDownEl.className = '';
                pullDownEl.querySelector('.pullDownLabel').innerHTML = '下拉刷新...';
                this.minScrollY = -pullDownOffset;
            } else if (this.y < (this.maxScrollY - 5) && !pullUpEl.className.match('flip')) {
                console.log(16);
                pullUpEl.className = 'flip';
                pullUpEl.querySelector('.pullUpLabel').innerHTML = '松手開始更新...';
                this.maxScrollY = this.maxScrollY;
            } else if (this.y > (this.maxScrollY + 5) && pullUpEl.className.match('flip')) {
                console.log(17);
                pullUpEl.className = '';
                pullUpEl.querySelector('.pullUpLabel').innerHTML = '上拉加載更多...';
                this.maxScrollY = pullUpOffset;
            }
        },
        //onScrollEnd:表示用戶下拉刷新完,放開手指時所顯示的不同的交互文字
        onScrollEnd: function () {
            if (pullDownEl.className.match('flip')) {
                console.log(12);
                pullDownEl.className = 'loading';
                pullDownEl.querySelector('.pullDownLabel').innerHTML = '加載中...';                
                pullDownAction();    // Execute custom function (ajax call?)
            } else if (pullUpEl.className.match('flip')) {
                console.log(13);
                pullUpEl.className = 'loading';
                pullUpEl.querySelector('.pullUpLabel').innerHTML = '加載中...';                
                pullUpAction();    // Execute custom function (ajax call?)
            }
        }
    });
    
    setTimeout(function () { document.getElementById('wrapper').style.left = '0'; }, 800);
}
/*
  touchmove:表示手指在屏幕上滑動連續觸發的事件
*/
document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);
/*
  load事件:僅在所有資源都完全加載后才被觸發
  DOMContentLoaded:DOM加載之后及資源加載之前被觸發.
*/    
document.addEventListener('DOMContentLoaded', function () { setTimeout(loaded, 200); }, false);
View Code
5、對iScroll進行實例化的幾種方法:
  5.1、使用onDOMContentLoaded事件實現滾動(本文使用的就是這種)
         適用於滾動內容只包含文字、圖片,並且所有的圖片都有固定的尺寸
    注意:myscroll這個變量是全局的,因此你可以在任何地方調用它
 <script>
  var myscroll;
  function loaded(){
      myscroll=new iScroll("wrapper"); 
  } 
  window.addEventListener("DOMContentLoaded",loaded,false); 
</script>

      5.2、使用onLoad事件實現滾動

       因為DOMContentLoaded事件是載入DOM結構后就會被調用,所以在圖片等元素未載入前可能無法確定滾動區域的長寬,此時可以使用onLoad事件來實現。

<script> 
var myscroll; 
function loaded(){
     setTimeout(
            function(){ 
            myscroll=new iScroll("wrapper"); },100 );
     }
     window.addEventListener("load",loaded,false); 
</script>

這種情況下iScroll會在頁面資源(包括圖片)加載完畢100ms之后得到初始化,這應該是一種比較安全的調用iScroll的方式。

  5.3、inline初始化

    這種情況會在頁面加載到js的時候就進行調用,此方法不推薦使用。

<script src="iscroll.js"></script>
        <div id="wrapper">
                   <ul>
                         <li></li>
                           ...
                  </ul>
        </div>
<script>
       var myscroll=new iScroll("wrapper");
</script>

  如果你需要使用的話,可以建議你使用一些框架的ready方法來安全調用iScroll(比如jquery里的ready())。

6、 iScroll里傳遞的參數

  iScroll里的第二個參數允許你自定義一些內容,比如下面的這段代碼:

<script>
       var myscroll=new iScroll("wrapper",{
      hScrollbar:false,
      vScrollbar:false}
    );
</script>

        第二個參數通常都是一個對象,像上面的這個例子里就設定了不顯示滾動條。常用的參數如下:
               hScroll                 false 禁止橫向滾動 true橫向滾動 默認為true
               vScroll                 false 精致垂直滾動 true垂直滾動 默認為true
               hScrollbar            false隱藏水平方向上的滾動條
               vScrollbar            false 隱藏垂直方向上的滾動條
               fixedScrollbar      在iOS系統上,當元素拖動超出了scroller的邊界時,滾動條會收縮,設置為true可以禁止滾動條超出
                                        scroller的可見區域。默認在Android上為true, iOS上為false
               fadeScrollbar     false 指定在無漸隱效果時隱藏滾動條
               hideScrollbar     在沒有用戶交互時隱藏滾動條 默認為true
               bounce             啟用或禁用邊界的反彈,默認為true
               momentum       啟用或禁用慣性,默認為true,此參數在你想要保存資源的時候非常有用
               lockDirection       false取消拖動方向的鎖定, true拖動只能在一個方向上(up/down 或者left/right)

7、各種效果的實現

  7.1、滾動刷新  ‘Pull to refresh’ demo

     你只需要做的就是自定義pullDownAction()這個方法。你可能需要一個ajax來加載新的內容,不過一旦DOM樹發生了變化要記得調用refresh這個方法來。

     需要記住的是在例子中我們加了1秒的延遲來模擬網絡的延遲效果。 

     7.2、縮放(pinch / zoom)

  只需要設置放大的參數zoom 為true即可實現利用手勢來放大和縮小。雙擊放大和縮小的功能在iScroll 4里也是得到支持的。配置如下:

var myScroll =new iScroll("wrapper",{zoom:true});

    7.3、捕捉元素(snap and snap to element)  ‘Carousel’ demo

  SNAP功能是判斷元素是否滑動到指定位置。通過這個效果可以制作花哨的跑馬燈效果。

  插件會自動分析滾動區域內相同標簽或相同大小的元素做為捕捉對象,也可以通過參數指定捕捉的對象。

var myscroll=new iScroll("wrapper",{
      snap:true,
      momentum:false,
      hScrollbar:false,
      vScrollbar: false
});

    可以通過設置snap參數為指定標簽來設定捕捉對象。比如捕捉li標簽。  

var myscroll=new iScroll("wrapper",{
      snap:"li",
      momentum:false,
      hScrollbar:false,
      vScrollbar:false
});

在這個例子中scroller可以捕捉到滾動區域中最左上角的li元素 。

     7.4、自定義滾動條(custom scrollbars)

         在iScroll 4這個版本中,可以利用一系列的css來自定義滾動條的呈現。可以給滾動條添加一個class參數,如下:

var myscroll=new iScroll("wrapper",{
  scrollbarClass: "myScrollbar"
});

    需要提醒的是,滾動條是由兩個元素組合而成的:容器和顯示器。容器同wrapper的高度相同,而顯示器則代表的是滾動條本身。
           滾動條的HTML結構如下: 

<div class="myScrollbarV">
           <div></div>
</div>
      .myscrollbarV{
              position:absolute;z-index:100;width:8px;bottom:7px;top:2px;right:1px;
       }
       .myScrollbarV > div {
            position:absolute;
            z-index:100;
            width:100%;
            /* The following is probably what you want to customize */
           background:-webkit-gradient(linear, 0 0, 100% 0, from(#f00), to(#900));
             border:1px solid #800;
            -webkit-background-clip:padding-box;
            -webkit-box-sizing:border-box;
            -webkit-border-radius:4px;
            -webkit-box-shadow:inset 1px 1px 0 rgba(255,255,255,0.5);
         }
View Code

8、通用方法:

     (1)refresh:在DOM樹發生變化時,應該調用此方法

      eg: setTimeout(function () { myScroll.refresh(); }, 0); 

     (2)iScroll還提供了scrollTo, scrollToElement和scrollToPage三個方法讓你能夠通過javascript來控制滾動效果。

    scrollTo(x, y, time, relative):在指定的time時間內讓內容滾動條x/y的位置。如myScroll.scrollTo(0, -100, 200) 在200毫秒內Y軸向下滾動100像素。myScroll.scrollTo(0, 10, 200, true)可以實現相對當前位置在200毫秒內Y軸向上滾動10像素的效果。

    scrollToElement(element, time):在指定的時間內滾動到指定的元素。如myScroll.scrollToElement(‘li:nth-child(10)’, 100) 在100毫秒內滾動到第10個li元素的位置。第1個參數可以用CSS3中的選擇器來篩選元素。

    snapToPage(pageX, pageY, time):在200毫秒內從第1頁滾動到第2頁(0代表第1頁,1代表第2頁)。這個使用SNAP功能的時候可以調用這個函數。

   (3)detroy():完全消除myscroll及其占用的內存空間
                eg: myscroll.destroy();

        myScroll = null;

9、iScroll的發展方向

  • 表單域的支持
  • 縮放的優化
  • 更好的桌面瀏覽器的兼容性
  • onScrol事件的優化
  • 加個哈希值的變化
  • DOM改變后自動刷新

    

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM