前端拖拽排序插件的实现——讲一个六耳猕猴和孙悟空的故事

插件的整体功能参考的是支付宝的付款顺序拖拽

发文章之前还未对该插件进行封装及美化,但具体的功能已经实现,有需要源码的留邮箱

先说说一个拖拽功能的实现思路

其实类似于六耳猕猴和孙悟空的关系

一只是真猴子,另一只也是真猴子,不能说六耳猕猴是个假猴子,他确实在西游记的某几集里出现一下,代替了一下孙悟空,只目的不纯,而且有点假,把这个例子类比到拖拽,跟下图差不多

事实上,九九八十一难,还是孙悟空来经历,至于顺序,则是可以随意排序的(你说了算)

当你把其中一只孙悟空拖起来的时候,就在唐僧身边安插一只六耳猕猴,从图中可以看到,孙悟空被拖起来腾云驾雾去了,六耳猕猴很假的呆在孙悟空该呆的位置。这是第一个关键点,在真猴王起飞的一瞬间,就要安插一只假猴子来取经(代码只看个思路,具体代码不全)

 

//第一步,记录是否第一个或者最后一个节点,在原先节点的位置是补一个假的节点
  var prevNode = $(this).prev();
  var nextNode = $(this).next();
  if(prevNode.length==0){
    nextNode.before("<li class='animLi'>六耳猕猴</li>");
  }else{
    prevNode.after("<li class='animLi'>六耳猕猴</li>");
  }
  //把当前css改成fixed,不用absolute防止relative问题
  $(this).css({"position":"fixed","left":nodeLeft,"top":nodeTop,"opacity":0.5});

第二个关键点,孙悟空想去哪儿,六耳猕猴就得跟到哪儿(纯属虚构),但是,孙悟空也不能xjb飞,他得有个界限,不能超过了这九九八十一难去飞,所以写的时候要注意两个边界。(具体代码不是很好懂,大概注释一下,过程和思路比较重要)

 

 //第二步,绑定mousemove事件,并判断鼠标移动是否超过Li.height
  $(this).on("mousemove",function(ev){
    ifPassHalf(ev,mouseTop,$(this),nodeTop,$("ul").scrollTop())
  });
function ifPassHalf(ev,mouseTop,node,nodeTop,scrollTop){
  node.css("top",nodeTop+ev.pageY - mouseTop);
  var newscrollTop = scrollTop;
  var zNodeTop = node.offset().top;
  var jNodeTop = $(".animLi").offset().top;
  var ifPassHalf = zNodeTop - jNodeTop;
  //第1层判断,判断鼠标是否超出ul框,不让节点移出ul的上边界和下边界
  if(parseInt(node.offset().top) <= parseInt(node.parent().offset().top)){
    node.css("top",node.parent().offset().top+30);
    //该事件在节点碰到顶部边界的时候触发,把滚动条移动加进去
    $(".animLi").prev().before($(".animLi"));
    newscrollTop = scrollTop - parseInt(node.height());
  }else if((node.offset().top-node.parent().height()+parseInt(node.height())) >= parseInt(node.parent().offset().top)){
    node.css("top",parseInt(node.parent().offset().top)+parseInt(node.parent().height())-node.height()-30);
    //该事件在节点碰到底部边界的时候触发,把滚动条移动加进去
    $(".animLi").next().after($(".animLi"));
    newscrollTop = scrollTop + parseInt(node.height());
  }else{
     //假节点跟着真节点飞的代码
    if(ifPassHalf>51){
      $(".animLi").next().after($(".animLi"));
    }else if(ifPassHalf<-51){
      $(".animLi").prev().before($(".animLi"));
    }
  }
//考虑滚动条
  node.parent().scrollTop(newscrollTop);
}

第三个关键点,就是孙悟空想下来了,六耳猕猴就得走开,就得消失。

 

function putNodeDown(ev){
  $(".animLi").hide();
  $(".animLi").after($(this));
  $(this).removeAttr("style");
  //把mousemove mouseout事件解绑了
  $(this).off("mousemove");
  $("li").off("mouseout");
  //把六耳猕猴让给孙悟空
  $(".animLi").remove();
}


插播一个bug的解决方案,就是鼠标拖动过快,或者超过边界的时候,应当有个mouseout事件去做一些处理,代码如下

 

  //修复鼠标移动过快移出div的bug
  $("li").on("mouseout",function(){
    $(".animLi").hide();
    $(".animLi").after($(this));
    $(this).removeAttr("style");
    $(this).off("mousemove");
    $(".animLi").remove();
    $("li").off("mouseout");
    alert("请规范操作,鼠标不要超出拖拽区域");
  });
}

整体的过程如下

鼠标点下(孙悟空起飞,六耳猕猴插队)-->鼠标移动(猴子乱飞,六耳猕猴跟着去各个位置报道)-->鼠标弹起(猴子归位,六耳猕猴走开)

就是那么简单(走了好多弯路的我表示,简单个jer)

需要源码的留邮箱,代码托管在码云,并不想提交,因为还没写完

还是补一篇源码,拿去直接用,反正也不长。

 

<!DOCTYPE html>
<html>
<head>
  <meta charset=utf-8>
  <title>拖动测试</title>
  <style>
    ul{
      list-style-type: none; 
      width: 600px;
      height: 800px;
      box-sizing: border-box;
      border:1px solid black;
      overflow-y: scroll;
      overflow-x: hidden;
      padding: 0;
      margin: auto;
      position: relative;
      margin-top:20px;
    }
    li{
      list-style:none; 
      height: 100px;
      width:  600px;
      background-color: green;
      box-sizing: border-box;
      border-bottom: 1px solid blue; 
      float: left;
      cursor: move;
    }
    .animLi{  
      background-color: white;
      height: 100px;
    }
    @keyframes anmi
    {
      from {height:20px}
      to {height:100px}
    }
  </style>
</head>
<body>
<ul>
  <li index=1>孙悟空</li>  
  <li index=2>孙悟空</li>  
  <li index=3>孙悟空</li>  
  <li index=4>孙悟空</li>  
  <li index=5>孙悟空</li>  
  <li index=6>孙悟空</li>  
  <li index=1>孙悟空</li>  
  <li index=2>孙悟空</li>  
  <li index=3>孙悟空</li>  
  <li index=4>孙悟空</li>  
  <li index=5>孙悟空</li>  
  <li index=6>孙悟空</li>  
  <li index=1>孙悟空</li>  
  <li index=2>孙悟空</li>  
  <li index=3>孙悟空</li>  
  <li index=4>孙悟空</li>  
  <li index=5>孙悟空</li>  
  <li index=6>孙悟空</li>  
  <li index=1>孙悟空</li>  
  <li index=2>孙悟空</li>  
  <li index=3>孙悟空</li>  
  <li index=4>孙悟空</li>  
  <li index=5>孙悟空</li>  
  <li index=6>孙悟空</li>  
  <li index=1>孙悟空</li>  
  <li index=2>孙悟空</li>  
  <li index=3>孙悟空</li>  
  <li index=4>孙悟空</li>  
  <li index=5>孙悟空</li>  
  <li index=6>孙悟空</li>  
</ul>
<script src="js/jquery-1.11.1.js"></script>
<script>
//去掉鼠标选中文字的事件
if(document.all){
    document.onselectstart= function(){return false;}; //for ie
}else{
    document.onmousedown= function(){return false;};
    document.onmouseup= function(){return true;};
}
document.onselectstart = new Function('event.returnValue=false;');

$("li").on("mousedown",drag);

function drag(ev){
  //鼠标距离顶部的高度,用于计算移动后的高度差
  var mouseTop = ev.pageY;

  //节点距离顶部的高度和宽度,用于绝对定位
  var nodeTop = $(this).offset().top;
  var nodeLeft = $(this).offset().left;

  //第一步,记录是否第一个或者最后一个节点
  var prevNode = $(this).prev();
  var nextNode = $(this).next();
  if(prevNode.length==0){
    nextNode.before("<li class='animLi'>六耳猕猴</li>");
  }else{
    prevNode.after("<li class='animLi'>六耳猕猴</li>");
  }
  //把当前css改成fixed,不用absolute防止relative问题
  $(this).css({"position":"fixed","left":nodeLeft,"top":nodeTop,"opacity":0.5});
  //在节点原先呆的位置上补一个假的

  //第二步,绑定mousemove事件,判断鼠标移动是否超过Li.height
  $(this).on("mousemove",function(ev){
    ifPassHalf(ev,mouseTop,$(this),nodeTop,$("ul").scrollTop())
  });

  //第三步,解绑mousemove事件,绑定mouseup事件
  $(this).on("mouseup",putNodeDown);

  //修复鼠标移动过快移出div的bug
  $("li").on("mouseout",function(){
    $(".animLi").hide();
    $(".animLi").after($(this));
    $(this).removeAttr("style");
    $(this).off("mousemove");
    $(".animLi").remove();
    $("li").off("mouseout");
    alert("请规范操作,鼠标不要超出拖拽区域");
  });
}

function ifPassHalf(ev,mouseTop,node,nodeTop,scrollTop){
  node.css("top",nodeTop+ev.pageY - mouseTop);
  var newscrollTop = scrollTop;
  var zNodeTop = node.offset().top;
  var jNodeTop = $(".animLi").offset().top;
  var ifPassHalf = zNodeTop - jNodeTop;
  //第1层判断,判断鼠标是否超出ul框,不让节点移出ul的上边界和下边界
  if(parseInt(node.offset().top) <= parseInt(node.parent().offset().top)){
    node.css("top",node.parent().offset().top+30);
    //该事件在节点碰到顶部边界的时候触发,把滚动条移动加进去
    $(".animLi").prev().before($(".animLi"));
    newscrollTop = scrollTop - parseInt(node.height());
  }else if((node.offset().top-node.parent().height()+parseInt(node.height())) >= parseInt(node.parent().offset().top)){
    node.css("top",parseInt(node.parent().offset().top)+parseInt(node.parent().height())-node.height()-30);
    //该事件在节点碰到底部边界的时候触发,把滚动条移动加进去
    $(".animLi").next().after($(".animLi"));
    newscrollTop = scrollTop + parseInt(node.height());
  }else{
    if(ifPassHalf>51){
      $(".animLi").next().after($(".animLi"));
    }else if(ifPassHalf<-51){
      $(".animLi").prev().before($(".animLi"));
    }
  }
  node.parent().scrollTop(newscrollTop);
}

function putNodeDown(ev){
  $(".animLi").hide();
  $(".animLi").after($(this));
  $(this).removeAttr("style");
  //把mousemove mouseout事件解绑了
  $(this).off("mousemove");
  $("li").off("mouseout");
  //把六耳猕猴让给孙悟空
  $(".animLi").remove();
}
</script>
</body>
</html>

 

 

 

 

 

 

 


 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值