这个效果要注意几点:
1.注意碰撞检测。
2.注意两个元素之间的距离,原理是根据三角形定理。
废话不多说,有不明白的地方可以qq我或者留言,大家一起讨论,谢谢!
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>无标题文档</title>
<style type="text/css">
*{ padding:0; margin:0}
ul,li{ list-style:none}
.box{ width:311px; border:3px solid #000; margin:50px 200px; overflow:hidden;zoom:1; }
.box ul{ width:305px; overflow:hidden;zoom:1; position:relative; height:450px}
.box ul li{ width:90px; background:#06C; float:left; height:100px; font-weight:bolder; color:#FFF; font-size:24px; text-align:center; margin:5px; line-height:100px}
.cur{ cursor:move;}
.hig{ border:2px dotted #FFFFFF}
</style>
</head>
<body>
<div class="box" id="moveBox">
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
<li>10</li>
<li>11</li>
<li>12</li>
</ul>
<script>
var oBox=document.getElementById("moveBox");
var oUl=oBox.getElementsByTagName("ul")[0];
var oLi=oUl.getElementsByTagName("li");
var aPos = [];
var zx=0;
//布局转换
for (var i = 0; i < oLi.length; i++)
{
oLi[i].index = i;
oLi[i].style.top = oLi[i].offsetTop + "px";
oLi[i].style.left = oLi[i].offsetLeft + "px";
aPos.push({"left":oLi[i].offsetLeft, "top":oLi[i].offsetTop})
}
for(var i=0;i<oLi.length;i+=1){
oLi[i].style.position="absolute";
drap(oLi[i]);
}
//拖拽函数
function drap(obj){
obj.οnmοusedοwn=function(e){
var oNear=null;
var ev=e||window.event;
var disX=ev.clientX-this.offsetLeft-oUl.offsetLeft;
var disY=ev.clientY-this.offsetTop-oUl.offsetTop;
this.className="cur";
this.style.zIndex=zx++;
if(obj.setCapture){
obj.setCapture();
}else{
window.captureEvents(Event.MOUSEMOVE);
}
ev.cancelBubble = true;//阻止事件冒泡,防止冲突
document.οnmοusemοve=function(e){
var ev=e||window.event;
var w=ev.clientX-disX-oUl.offsetLeft;
var h=ev.clientY-disY-oUl.offsetTop;
(w<0)&&(w=0);
(w>=(oUl.offsetWidth-obj.offsetWidth))&&(w=(oUl.offsetWidth-obj.offsetWidth));
(h<0)&&(h=0);
(h>=(oUl.offsetHeight-obj.offsetHeight))&&(w=(oUl.offsetHeight-obj.offsetHeight));
obj.style.top=h+"px";
obj.style.left=w+"px";
for(var i=0;i<oLi.length;i++){
oLi[i].className="";
}
oNear=findObj(obj);
oNear && (oNear.className="hig");
}
document.οnmοuseup=function(){
if(obj.releaseCapture){
obj.releaseCapture();
}else{
window.releaseEvents(Event.MOUSEMOVE|Event.MOUSEUP);
}
document.οnmοuseup=null;
document.οnmοusemοve=null;
for(var i=0;i<oLi.length;i++){
oLi[i].className="";
}
if(oNear){
oNear.style.zIndex=zx++;
startMove(obj,aPos[oNear.index]);
startMove(oNear,aPos[obj.index]);
var temp=oNear.index;
oNear.index=obj.index;
obj.index=temp;
}else{
startMove(obj,aPos[obj.index]);
}
return false;
}
}
}
//找出相遇点中最近的元素
function findObj(obj){
var arr1=[];
var arr2=[];
var res=null;
var minnum=9999999;
var minLi=null;
for(var i=0;i<oLi.length;i++){
res=isButt(obj,oLi[i]);
if(oLi[i]!=obj&&res){
arr1.push(dian(obj,oLi[i]));
arr2.push(oLi[i]);
}
}
for(var i=0;i<arr1.length;i++){
if(arr1[i]<minnum){
minnum=arr1[i];
minLi=arr2[i];
}
}
return minLi;
}
//求亮点之间的距离
function dian(obj1,obj2){
var a=(obj1.offsetLeft + obj1.offsetWidth / 2) - (obj2.offsetLeft + obj2.offsetWidth / 2);
var b=(obj1.offsetTop + obj1.offsetHeight / 2) - (obj2.offsetTop + obj2.offsetHeight / 2);
return Math.sqrt(a*a+b*b);
}
//碰撞检测
function isButt(aObj,bObj){
var a1=aObj.offsetLeft;
var b1=aObj.offsetTop;
var c1=aObj.offsetLeft+aObj.offsetWidth;
var d1=aObj.offsetTop+aObj.offsetHeight;
var a2=bObj.offsetLeft;
var b2=bObj.offsetTop;
var c2=bObj.offsetLeft+bObj.offsetWidth;
var d2=bObj.offsetTop+bObj.offsetHeight;
if(a2>c1||b2>d1||a1>c2||b1>d2){
return false;
}else{
return true;
}
}
//获取最终样式
function getStyle(obj, attr)
{
return parseFloat(obj.currentStyle ? obj.currentStyle[attr] : getComputedStyle(obj, null)[attr])
}
//运动框架
function startMove(obj, pos, onEnd)
{
clearInterval(obj.timer);
obj.timer = setInterval(function ()
{
doMove(obj, pos, onEnd)
}, 30)
}
function doMove(obj, pos, onEnd)
{
var iCurL = getStyle(obj, "left");
var iCurT = getStyle(obj, "top");
var iSpeedL = (pos.left - iCurL) / 5;
var iSpeedT = (pos.top - iCurT) / 5;
iSpeedL = iSpeedL > 0 ? Math.ceil(iSpeedL) : Math.floor(iSpeedL);
iSpeedT = iSpeedT > 0 ? Math.ceil(iSpeedT) : Math.floor(iSpeedT);
if (pos.left == iCurL && pos.top == iCurT)
{
clearInterval(obj.timer);
onEnd && onEnd()
}
else
{
obj.style.left = iCurL + iSpeedL + "px";
obj.style.top = iCurT + iSpeedT + "px";
}
}
</script>
</div>
</body>
</html>