zoukankan      html  css  js  c++  java
  • jquery 拖拽排序分析

      今天应一个朋友的委托,研究一下拖拽排序,我记得我上次写拖拽排序,因为方法太死板,效果我一直不是很满意,一直想再从写一个,一直没机会(懒),这次因为公司部门变动所以有了一些时间(无聊)来写,本来准备使用Vue写,奈何功夫不到家在自定义指令的时候,问题卡住了,研究了一段时间之后,还是决定放弃,研究一下Vue再来写过,所以本次还是用了Jquery来写。

      

      直接上代码

      这是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部分   

    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部分

       

      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,中的判断影子元素位置的地方,对数组的操作,需要注意的还有,当产生滚动条的时候,需要吧滚动距离给加上,否则会错位。

          不说了,我得去找工作了,加油!

          以上

          2017-04-26  击鼓卖糖

  • 相关阅读:
    VS2012配色方案
    ”Metro UI之磁贴(二)
    hdu 1068
    3.11 从多个表中返回丢失的数据
    腾讯马化腾:云服务的安全问题是我最忧虑的(通过云,180多人能挣了10亿美金的利润)
    王小川清华大学毕业典礼演讲:我也有过学渣经历(和时间做朋友,要和华军、天空这些下载站做合作推广)
    今天看到一个签名,有点意思
    DEP受保护的问题(尤其是Outlook)
    竹林蹊径-深入浅出Windows内核开发作者的博客
    Sublime和Codeblocks支持C++11
  • 原文地址:https://www.cnblogs.com/dongwy/p/6767610.html
Copyright © 2011-2022 走看看