RE:通過移動(dòng)端滑動(dòng)手勢(shì)實(shí)現(xiàn)數(shù)據(jù)加載

背景:

基于要嘗試的移動(dòng)端項(xiàng)目需要有一個(gè)通過上拉下滑手勢(shì)達(dá)成加載不同數(shù)據(jù)的功能,其涉及到滑動(dòng)手勢(shì)和ajax數(shù)據(jù)加載方面的知識(shí)點(diǎn)。故對(duì)整個(gè)實(shí)現(xiàn)過程做一個(gè)記錄整理。個(gè)人JS功底有限,看了諸多例子和對(duì)于移動(dòng)端手勢(shì)知識(shí)點(diǎn)梳理的技術(shù)博客才做到了對(duì)功能的實(shí)現(xiàn)。并且也在這個(gè)過程中初步了解到了移動(dòng)端框架Zepto.js。(:з」∠) 當(dāng)然,最后還是選擇了盡量用原生來實(shí)現(xiàn)這一功能。因?yàn)檫@樣才能夠?qū)φ麄€(gè)功能實(shí)現(xiàn)原理理解上更充分些,想盡量少依賴于插件。不過到了數(shù)據(jù)加載上,因?yàn)闀r(shí)間成本等原因最后還是用上了JQuery來實(shí)現(xiàn)ajax的部分。

功能描述:

如下圖所示,黃色圓圈為鼠標(biāo),當(dāng)前可以通過上滑和下滑的手勢(shì)來切換上一周和下一周的數(shù)據(jù)信息。而當(dāng)翻到首頁或尾頁時(shí),會(huì)出現(xiàn)提示頁告知。除開用JS控制判斷的手勢(shì)和獲取的信息狀態(tài)來輸出不同的頁面,就是用AJAX來獲取具體的JSON數(shù)據(jù)。

效果展示:

滑動(dòng)部分實(shí)現(xiàn):

1.獲取手指觸碰到屏幕時(shí)的坐標(biāo) (x,y);
2.在限定單手指觸碰的大前提下再獲取移動(dòng)后手指在屏幕的坐標(biāo)位置(x1,y2);
3.使用if來控制坐標(biāo) (x,y)與結(jié)束坐標(biāo)(x1,y2)之間的垂直與水平數(shù)值差距,將滑動(dòng)范圍限定起來;
4.符合條件的可加載出相應(yīng)指定數(shù)據(jù)。

相關(guān)鏈接:

原生JS實(shí)現(xiàn)觸摸滑動(dòng)事件http://dobit.top/Detail/109.html
玩轉(zhuǎn)H5上拉下滑動(dòng)效https://isux.tencent.com/h5-drop-down-effect-slide.html
開源移動(dòng)端元素拖拽慣性彈動(dòng)以及下拉加載兩個(gè)JShttp://www.zhangxinxu.com/wordpress/2017/01/mobile-phone-drag-drop-inertia-loading/

基本是復(fù)制原生JS實(shí)現(xiàn)觸摸滑動(dòng)事件的代碼后簡(jiǎn)化改動(dòng)部分功能來實(shí)現(xiàn)這個(gè)滑動(dòng)動(dòng)效的。并且關(guān)于if方面的控制,需要自己再改善。而其他兩個(gè)例子有給我啟發(fā)的地方。而且那兩個(gè)例子的相關(guān)講解也很詳細(xì),是值得記錄的。
如果各位看官仔細(xì)對(duì)比原生JS實(shí)現(xiàn)觸摸滑動(dòng)事件鏈接中的代碼,會(huì)發(fā)現(xiàn)真沒啥大的區(qū)別,而我寫這篇文的目的也只是著重于技術(shù)點(diǎn)的記錄匯總,以及對(duì)代碼進(jìn)行自己的理解分析加深印象。當(dāng)然,不排除我對(duì)于這個(gè)效果中一些代碼的理解是錯(cuò)誤的。希望在以后自己的JS技能更成熟以后,能夠再回來修改這個(gè)帖子。
現(xiàn)在開始以上圖項(xiàng)目為例,分述。

<div class="myweekly">
  <!--刷新圖標(biāo),當(dāng)有新內(nèi)容加載時(shí),顯示該圖標(biāo),加載完成后圖標(biāo)隱藏-->
  <div id="refreshTop"></div>
  <div id="pullup">下拉顯示上一周</div>
      
  <form role="form"  class="info-box my-weekly-box"  id="show">
     <!--中間刷新區(qū)域-->
  </form>
      
  <div id="pulldown">上拉顯示下一周</div>
  <!--刷新圖標(biāo),當(dāng)有新內(nèi)容加載時(shí),顯示該圖標(biāo),加載完成后圖標(biāo)隱藏-->
  <div id="refreshbottom"></div>
</div>

var mytouch = (function() {
      //先設(shè)置相關(guān)變量
      var x, y,
          doc = document,
          imgWidth=doc.getElementById("show").clientWidth,//中間顯示區(qū)域
          pullup = doc.getElementById("pullup"),//頂部區(qū)域
          pulldown = doc.getElementById("pulldown"),//底部區(qū)域
          isMoved = true; //布爾值,用作阻斷事件多次觸發(fā)
  return{ //返回對(duì)象
      tStart: function(event) { //設(shè)置動(dòng)態(tài)參數(shù)來獲取最開始時(shí)觸摸到屏幕的坐標(biāo)信息
            if (isMoved) {
               //使用touches接收參數(shù)位于當(dāng)前對(duì)象觸摸點(diǎn)的集合列表(如x軸、y軸坐標(biāo)數(shù)據(jù)信息等)
               var touches = event.targetTouches;

               //獲取當(dāng)前對(duì)象所有觸摸點(diǎn)的列表,判斷長(zhǎng)度即判斷是有幾個(gè)觸摸點(diǎn)。即當(dāng)有一個(gè)手指最初觸摸屏幕時(shí)獲取坐標(biāo)
               if (touches.length == 1) {
                   x = touches[0].pageX;
                   y = touches[0].pageY;
               }
            isMoved = false; //設(shè)置isMoved的值,之后滿足條件才會(huì)觸發(fā)后面的滑動(dòng)事件
            }
      },

以上為 步驟1 的實(shí)現(xiàn)。上面的函數(shù)還是比較復(fù)雜的,首先它是一個(gè)使用了函數(shù)標(biāo)識(shí)記法的自調(diào)匿名函數(shù),而它的返回值中還顯式返回了一個(gè)對(duì)象方法。如此,雖說自調(diào)匿名函數(shù)本身是最適合執(zhí)行一次性或初始化任務(wù)的,但因?yàn)榉祷刂蒂x值給了 mytouch 這個(gè)變量,該函數(shù)不僅具有自行調(diào)用的能力,我們也能像使用一般函數(shù)一樣調(diào)用它。
另外上述 var x,y,doc …… 這樣的寫法需要注意(:з」∠),聲明一個(gè)變量的時(shí)候漏掉了var,這個(gè)變量就會(huì)默認(rèn)成全局變量了。

var mytouch = (
    function() {
      …
    return{
        tStart: function(event){
                  …
                },
        …
    }
})();

以下開始正式進(jìn)入滑動(dòng)部分

tMove: function(event) { //手指在屏幕上移動(dòng)時(shí)觸發(fā)上/下滑事件
  if (!isMoved) { //只有手指第一次在屏幕上滑動(dòng)時(shí),并且滿足響應(yīng)條件,才觸發(fā)上/下滑事件
    var touches = event.targetTouches;
    if (touches.length == 1) { //一個(gè)手指在屏幕上
      var x1 = touches[0].pageX, //移動(dòng)到的坐標(biāo)
          y1 = touches[0].pageY;
          if ((y1 - 80) > y ){ //下滑手勢(shì)
           isMoved = true; //不設(shè)置該變量,會(huì)導(dǎo)致多個(gè)touchmove事件
            //下滑刷新加載頁面,顯示頂部刷新圖標(biāo)
            doc.getElementById("refreshTop").style.display = "block";
            //隱藏 “下滑顯示上一周”的文字提示
            doc.getElementById("pullup").style.display = "none";
         
             setTimeout(function() { //開始獲取數(shù)據(jù)
             //隱藏頂部刷新圖標(biāo)”
             doc.getElementById("refreshTop").style.display = "none";
             //顯示 “下滑顯示上一周”的文字提示
             doc.getElementById("pullup").style.display = "block";
             //這里的 nw 為周數(shù),在這里也可把它當(dāng)索引值,通過改變它,改變獲取的JSON數(shù)據(jù)信息。
             nw --; 
                           
             //開始使用JQueryAjax獲取后臺(tái)數(shù)據(jù),如果為純前端,
               可直接用 innerHTML屬性輸出頁面內(nèi)容
    $.getJSON("/api/weekly.php?week="+ nw +"&session="+session_id,function(json){
        if(nw<1){ //判斷翻到第一頁之后,不能夠繼續(xù)滑動(dòng)翻頁了。
          $("#show").html('<div><div>已經(jīng)翻到第一頁了!</div></div>');
             nw = 0;//如果不設(shè)置該變量,一直上翻的話,nw會(huì)為負(fù)數(shù),需要阻止進(jìn)程。
         }                             
         else{  
              //根據(jù)后臺(tái)接口的返回值判斷要輸出的內(nèi)容
              if(json.status=="已提交" && json.url!="無"){
               $("#show").html("");//避免刷新區(qū)域有多余html,先做空白刷新。
               $("#show").html(
                 '<div><label>周數(shù):</label><span id="nw">'+
                                     json.week + '周</span></div>' +
                 '<div><label>提交時(shí)間:</label><time id="time">'+ 
                                     json.time + '</time></div>' +
                 '<div><label>本周完成:</label><div>'+
                                     json.finished + '</div></div>' +
                 '<div><label>所遇到問題:</label><div>'+
                                     json.problem + '</div></div>' +
                 '<div><label>下周計(jì)劃:</label><div id="plan">'+
                                     json.plan + '</div></div>'  +
                 '<div><label>作品鏈接:</label><div>'+
                                     json.url + '</div></div>'
                  );//輸出JSON信息,點(diǎn)出JSON對(duì)象對(duì)應(yīng)的屬性值。    
               }
                 //獲得其他返回值時(shí),輸出其他內(nèi)容。
                   …… 
                 else{……}
                 }          
                return false;
             });                
          }, 500);
  }

該下滑部分注釋里已經(jīng)很詳細(xì)了。其中剛剛觸發(fā)下滑事件時(shí),刷新圖標(biāo)的出現(xiàn)/隱藏這里是需要改進(jìn)的。因?yàn)檫@里設(shè)置的是一個(gè)計(jì)時(shí)器,以“加載圖標(biāo)”出現(xiàn)的形式告知用戶數(shù)據(jù)正在加載。但是如果后臺(tái)數(shù)據(jù)沒有獲取成功,計(jì)時(shí)器的時(shí)間到了,那么該圖標(biāo)依舊會(huì)隱藏,而頁面仍然是空白的。對(duì)于這個(gè)問題,還沒能實(shí)際寫代碼解決,先在這里說一下解決思路,可以做一個(gè)判斷,即在ajax發(fā)消息,沒有收到返回值就一直是下拉顯示“加載圖標(biāo)”的狀態(tài),直到收到success的信息,就開始隱藏“加載圖標(biāo)”;直接收到error,頁面就僅彈上去不刷新;如果數(shù)據(jù)一直加載不到則設(shè)置“刷新超時(shí)”的提示。

if ((y1 + 80) < y ){ //上滑
   isMoved = true;
   //下滑刷新加載頁面,顯示頂部刷新圖標(biāo)
   doc.getElementById("refreshbottom").style.display = "block";
   //隱藏 “下滑顯示上一周”的文字提示
   doc.getElementById("pulldown").style.display = "none";
                        
    setTimeout(function() {
        doc.getElementById("refreshbottom").style.display = "none";
        doc.getElementById("pulldown").style.display = "block";
        nw ++;
      $.getJSON("/api/weekly.php?week="+ nw +"&session="+session_id,function(json){
          //避免出現(xiàn)其他狀態(tài),因?yàn)樵谠擁?xiàng)目中請(qǐng)假可以請(qǐng)到未來的周數(shù)        
          if(nw>offsetDays+1 && json.status =="未提交"){
              nw=offsetDays+2;//設(shè)置nw的值
              $("#show").html('<div><div>已經(jīng)翻到最后一頁了!</div></div>');
          }
                                          
       else{……
                                    
            }, 500);
          }
         }
        }
      },
    };
})();
document.addEventListener("touchstart", mytouch.tStart, false);
document.addEventListener("touchmove", mytouch.tMove, false);
return false;

addEventListener 的方法是為了給元素添加點(diǎn)擊事件,這里的false默認(rèn)的是事件句柄在冒泡階段執(zhí)行。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,716評(píng)論 25 709
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,022評(píng)論 4 61
  • (一) 不奢望,哪來的失望,不勉強(qiáng),又怎會(huì)迷惘,一路上,依靠著信仰。 朋友失戀了,她說,從一開始,我就知道自己輸了...
    奕辰兄閱讀 456評(píng)論 0 0
  • 1、《海天之戀》我的心情時(shí)刻倒影在你的心里你的容顏時(shí)刻印刻在我的身體你我是世界上最相愛的靈魂卻被,永遠(yuǎn)相隔于海天一...
    路人鋒閱讀 1,056評(píng)論 17 20
  • 昨天看到一則文章,仿佛看到了當(dāng)年自己室友的影子。 很記得大學(xué)有一年室友要拿助學(xué)金,因?yàn)樗业那闆r我們都很清楚,那時(shí)...
    當(dāng)你孤單想起誰閱讀 452評(píng)論 0 1

友情鏈接更多精彩內(nèi)容