jquery -- 拖拽排序分析

  今天應一個朋友的委託,研究一下拖拽排序,我記得我上次寫拖拽排序,由於方法太死板,效果我一直不是很滿意,一直想再從寫一個,一直沒機會(懶),此次由於公司部門變更因此有了一些時間(無聊)來寫,原本準備使用Vue寫,奈何功夫不到家在自定義指令的時候,問題卡住了,研究了一段時間以後,仍是決定放棄,研究一下Vue再來寫過,因此本次仍是用了Jquery來寫。css

  

  直接上代碼html

  這是CSS部分數組

 1     *{/*Css*/
 2  margin: 0px;
 3  padding: 0px;
 4  list-style: none;
 5  text-decoration: none;
 6  border: none;
 7  color: #000;
 8  text-shadow: none;
 9  box-shadow: none;
10  outline: none 11         }
12  button, ul {
13  margin-left: 20px;
14         }
15  ul li{
16  background: #AAABCA;
17  margin: 3px 0px;
18  width: 200px;
19  overflow: hidden;
20         }
21  ul li span{
22  float: right;
23  padding: 0px 3px;
24         }
25  ul li.on{
26  height: 50px;
27         }
28  ul li span:hover{
29  background: #ccc;
30  cursor: pointer;
31         }
32  button{
33  padding: 10px;
34  cursor: pointer;
35         }

    HTML部分   app

1 <button id="add">add</button>
2 <ul class="list">
3     <li>item1 4         <span class="remo">X</span>
5         <span class="goUp">^</span>
6         <span class="goDown">V</span>
7     </li>
8 </ul>

    Js部分dom

   

 1 $(function(){  2         //---------
 3         Array.prototype.min = function() {  4         var min = this[0];  5         var index = 0;  6         var len = this.length;  7         for (var i = 1; i < len; i++){  8             if (this[i] < min){  9                 min = this[i];  10  }  11  }  12         return min;  13  }  14         //---------
 15         var i = $('.list').find('li').length;  16         var cls = 'on';  17         $('#add').click(function(){  18             i++;  19             cls = cls?false:'on';  20             $('.list').append('<li class="'+cls+'">item'+i+' <span class="remo">X</span><span class="goUp">^</span><span class="goDown">V</span></li>');  21  addmous();  22 
 23  });  24  addmous();  25         var keyf = true;//變量控制第一次拖拽結束前,不容許其餘操做
 26         function addmous(){  27             $('.remo').off('mousedown').on('mousedown',function(){//綁定刪除元素
 28                 keyf = false;  29                 $(this).parent().remove();  30  });  31             $('.goUp').off('mousedown mouseup').on({'mousedown':function(){//向上按鈕
 32                 keyf = false;  33                 return false;  34             },'mouseup':function(){  35                 let $this = $(this).parent();  36                 let prev =  $this.prev();  37                 $this.after(prev);  38                 keyf = true;  39  }});  40             $('.goDown').off('mousedown mouseup').on({'mousedown':function(){//向下按鈕
 41                 keyf = false;  42             },'mouseup':function(){  43                 let $this = $(this).parent();  44                 let prev =  $this.next();  45                 $this.before(prev);  46                 keyf = true;  47                 return false;  48  }});  49             $('.list li').off('mousedown').on({'mousedown':moused,'mouseover':function(){  50                 return false;  51             }});//綁定mousedown事件
 52             var scrollLength = null;  53             function moused(ev){            //mousedown
 54                 if(keyf == false){return};//若是以前還有未完成的操做,那麼return
 55                 keyf = false;  56                 scrollLength = $(window).scrollTop() - 20;//保持滾動以後,不會錯位,爲了優化顯示效果,減去20
 57                 var allTop = [];  58                 var allLi = $('.list').find('li');  59                 for(var i = 0 ; i < allLi.length ; i++){//拿到ul當中全部li距離頂部的距離
 60  allTop.push(allLi.eq(i).offset().top);  61  }  62                 var _this = $(this);  63                 var l = $(this).offset().left;  64                 var t = $(this).offset().top - 3;  65                 let mX = ev.clientX,  66                     mY = ev.clientY + scrollLength,  67                     disX = mX - l,    //肯定鼠標按下的位置
 68                     disY = mY - t;  69                 $(this).css({'position': 'absolute','left':l +'px','top':t +'px'});//將點擊元素從不一樣文檔流中的元素,變成定位元素
 70                 var html = $(this).html();//拿到當前元素的 內容和class,複製成影子
 71                 var aCls = $(this).attr('class');  72                 $(this).after('<li class="addLi '+aCls+'" style="opacity:.4">'+html+'</li>');  73                 $(document).on({'mousemove':mousem,'mouseup':mouseu});  74                 //將move,up事件,綁定在document身上,防止快速拖拽容易丟失的問題
 75                 function mousem(ev){          //mousemove
 76                     keyf = false;  77                     var setArr = [];  78                     scrollLength = $(window).scrollTop() - 20; //解決滾動條問題
 79                     let mX = ev.clientX,  80                         mY = ev.clientY + scrollLength,//鼠標距離加上滾動的距離,防止滾動以後錯位
 81                         l = mX - disX;  82                         t = mY - disY;  83                     _this.css({'left':l+'px','top':t+'px'})//修改left,top造成拖拽
 84                     for(var i = 0 ;i < allTop.length ; i++){//循環以前拿到的全部Li的top數組
 85                         var zo = mY - allTop[i];  //使用鼠標的top,減去全部的li的top,(也就是鼠標到全部li的距離)
 86                         setArr.push(zo < 0?zo*-1:zo); //全部距離轉化成正數
 87  }  88                     var arrMin = setArr.min();//拿到鼠標到全部li的距離中的最小數(離鼠標最近li)
 89                     var minIndex = setArr.indexOf(arrMin,0);//查找距離鼠標最近的li的下標
 90                     var allLi2 = $('.list').find('li');  91                     if(minIndex == 0){//若是距離鼠標最近的是第一個
 92                         mY < allLi2.eq(0).offset().top ? allLi2.eq(0).before($('.addLi')):allLi2.eq(0).after($('.addLi'));  93                         //再判斷鼠標的的位置在不在第一個元素的上面,在上面,就往li[0]的前面插入,不然在後面插入
 94                     }else if (minIndex == allTop.length -1){  95                         //最後一個元素,和第一個道理同樣,寫法相反
 96                         mY > allLi2.eq(allTop.length).offset().top ? allLi2.eq(allTop.length).after($('.addLi')):allLi2.eq(allTop.length).before($('.addLi'));  97                     }else{  98                         //中間元素
 99                         allLi2.eq(minIndex).after($('.addLi'));//將影子插入到 距離鼠標最近li的後面
100  } 101  } 102                 function mouseu(){         //mouseup
103                     var ol = $('.addLi').offset().left;//拿到影子元素的座標
104                     var ot = $('.addLi').offset().top; 105                     $(document).off({'mousemove':mousem,'mouseup':mouseu});//將拖拽元素的left,top變化到影子的目標座標上
106                     _this.animate({'left':ol,'top':ot - 3},function(){//減3,是爲了優化視覺效果
107                         _this.css('position','static');//取消定位
108                         $('.addLi').after(_this);//將目標元素插入到影子元素後面
109                         $('.addLi').remove();//刪除影子元素
110                         keyf = true;//結束動做
111  }) 112  } 113                 return false
114  } 115             
116  } 117         
118     })

 

   嗯,其中的原理,我認爲在註釋當中寫的比較詳細了,自己難度沒有特別高,主要的思路就是:先把多個Li的offsetTop存成數組allTop,而後使用鼠標的Top值,減去allTop的每一項,生成新的數組setArr,setArr就是全部Li距離鼠標的距離,找到其中最小的值,就是距離鼠標最近的,而後找到最小值得在數組中的下標,也就是對應的dom元素Li在的下標,找到最近的Li以後,插入影子元素便可,主要在onmousemove,中的判斷影子元素位置的地方,對數組的操做,須要注意的還有,當產生滾動條的時候,須要吧滾動距離給加上,不然會錯位。優化

      不說了,我得去找工做了,加油!this

      以上spa

      2017-04-26  擊鼓賣糖prototype

相關文章
相關標籤/搜索