插件的整体功能参考的是支付宝的付款顺序拖拽
发文章之前还未对该插件进行封装及美化,但具体的功能已经实现,有需要源码的留邮箱
先说说一个拖拽功能的实现思路
其实类似于六耳猕猴和孙悟空的关系
一只是真猴子,另一只也是真猴子,不能说六耳猕猴是个假猴子,他确实在西游记的某几集里出现一下,代替了一下孙悟空,只目的不纯,而且有点假,把这个例子类比到拖拽,跟下图差不多
事实上,九九八十一难,还是孙悟空来经历,至于顺序,则是可以随意排序的(你说了算)
当你把其中一只孙悟空拖起来的时候,就在唐僧身边安插一只六耳猕猴,从图中可以看到,孙悟空被拖起来腾云驾雾去了,六耳猕猴很假的呆在孙悟空该呆的位置。这是第一个关键点,在真猴王起飞的一瞬间,就要安插一只假猴子来取经(代码只看个思路,具体代码不全)
//第一步,记录是否第一个或者最后一个节点,在原先节点的位置是补一个假的节点
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>