javascript实现类似google和msn space的拖拽
最近在网上看到一些朋友到处找类似于google的个性主页和msn space的拖拽实现,在下正好也找到了一个例子.但是问题比较多.我将其改写并完善,建立了一个通用的函数.具体的函数实现如下:
< html >
< html >
<
head
>
<
meta
http-equiv="Content-Type" content="text/html; charset=gb2312">
<
title
>
BlackSoul
的拖拽Demo</title>
<!--
____________________________________
|--------Author By BlackSoul---------|
|------------2006.03.30--------------|
|--------BlackSoulylk@gmail.com------|
|------------QQ:9136194--------------|
|------http://blacksoul.cnblogs.cn---|
======================================
-->
<
style
type="text/css">
body
{
margin:0px;
}
#aim
/*
设置目标层样式*/
{
position:absolute;/*
控制层的位置所必须的style*/
width:200px;
height:30px;
border:1px solid #666666;
background-color:#FFCCCC;
}
#sourceLayer
, #cloneLayer
{
position:absolute;/*
控制层的位置所必须的style*/
width:300px;
height:50px;
border:1px solid #666666;
background-color:#CCCCCC;
cursor:move;
}
.docked
{
display:none;
filter:alpha(opacity=100);
}
.actived
{
display:block;
filter:alpha(opacity=70);
}
</
style
>
</
head
>
<
body
>
<
div
id="aim">
放置范围</div>
<
div
id="sourceLayer" unselectable="off"><img src="http://blacksoul.gamenews.cn/mail.png" alt="
拖拽Demo">
拖拽Demo源</div>
<
div
id="cloneLayer" class="docked" unselectable="off"></div>
<
script
type="text/javascript" language="javascript">
<!--
/*
====================================
|--------Author By BlackSoul---------|
|------------2006.03.30--------------|
|--------BlackSoulylk@gmail.com------|
|------------QQ:9136194--------------|
|------http://blacksoul.cnblogs.cn---|
====================================
*/
//
设置层对象
var
aim;
var
sourceLayer;
var
cloneLayer;
//
定义各个层初始位置
var
aimX;
var
aimY;
var
orgnX;
var
orgnY;
//
拖拽过程中的变量
var
draging = false; //
是否处于拖拽中
var
offsetX = 0; //X
方向左右偏移量
var
offsetY = 0; //Y
方向上下偏移量
var
back; //
返回动画对象
var
thisX ; //
当前clone层的X位置
var
thisY ; //
当前clone层的Y位置
var
time ;
var
stepX ; //
位移速度
var
stepY ; //
位移速度
//
初始化拖拽信息
/*
initAimX
目标x坐标
initAimY
目标y坐标
initOrgnX
拖拽源x坐标
initOrgnY
拖拽源y坐标
*/
//
获得层对象
function
getLayer(inAim,inSource,inClone)
{
aim = document.getElementById(inAim);
sourceLayer = document.getElementById(inSource);
cloneLayer = document.getElementById(inClone);
}
function
initDrag(initAimX,initAimY,initOrgnX,initOrgnY)
{
aimX = initAimX;
aimY = initAimY;
orgnX = initOrgnX;
orgnY = initOrgnY;
//
设置各个开始层的位置
aim.style.pixelLeft = aimX;
aim.style.pixelTop = aimY;
sourceLayer.style.pixelLeft = orgnX;
sourceLayer.style.pixelTop = orgnY;
cloneLayer.style.pixelLeft = orgnX;
cloneLayer.style.pixelTop = orgnY;
}
//
准备拖拽
function
BeforeDrag()
{
if (event.button != 1)
{
return;
}
cloneLayer.innerHTML = sourceLayer.innerHTML; //
复制拖拽源内容
offsetX = document.body.scrollLeft + event.clientX - sourceLayer.style.pixelLeft;
offsetY = document.body.scrollTop + event.clientY - sourceLayer.style.pixelTop;
cloneLayer.className = "actived";
draging = true;
}
//
拖拽中
function
OnDrag()
{
if(!draging)
{
return;
}
//
更新位置
event.returnValue = false;
cloneLayer.style.pixelLeft = document.body.scrollLeft + event.clientX - offsetX;
cloneLayer.style.pixelTop = document.body.scrollTop + event.clientY - offsetY;
}
//
结束拖拽
function
EndDrag()
{
if (event.button != 1)
{
return;
}
draging = false;
if (event.clientX >= aim.style.pixelLeft && event.clientX <= (aim.style.pixelLeft + aim.offsetWidth) &&
event.clientY >= aim.style.pixelTop && event.clientY <= (aim.style.pixelTop + aim.offsetHeight))
{
//
拖拽层位于目标中,自动定位到目标位置
sourceLayer.style.pixelLeft = aim.style.pixelLeft;
sourceLayer.style.pixelTop = aim.style.pixelTop;
cloneLayer.className = "docked";
/*
**
这里完成之后可以用xml保存当前位置.
**
下次用户进入的时候
**
就初始化源拖拽层为xml当中的数据了
*/
}
else
{
//
拖拽位于目标层外,将拖拽源位置复原
thisX = cloneLayer.style.pixelLeft;
thisY = cloneLayer.style.pixelTop;
offSetX = Math.abs(thisX - orgnX);
offSetY = Math.abs(thisY - orgnY);
time = 500;//
设置动画时间
stepX = Math.floor((offSetX/time)*20);
stepY = Math.floor((offSetY/time)*20);
if(stepX == 0)
stepX = 2;
if(stepY == 0)
stepY = 2;
//
开始返回动画
moveStart();
}
}
function
moveStart()
{
back = setInterval("MoveLayer();",15);
}
//
设置返回的动画效果
function
MoveLayer()
{
//
位于目标左上
if(cloneLayer.style.pixelLeft <= orgnX && cloneLayer.style.pixelTop <= orgnY)
{
cloneLayer.style.pixelLeft += stepX;
cloneLayer.style.pixelTop += stepY;
//
如果位移超过目标则设置速度为pix.并向反方向回移.此处实现了弹簧效果.下同
if(cloneLayer.style.pixelLeft > orgnX)
{
stepX = 1;
}
if(cloneLayer.style.pixelTop > orgnY)
{
stepY = 1;
}
//
在X或Y轴上坐标相同则不发生位移
if(cloneLayer.style.pixelLeft == orgnX)
{
stepX = 0;
}
if(cloneLayer.style.pixelTop == orgnY)
{
stepY = 0;
}
if(cloneLayer.style.pixelLeft == orgnX && cloneLayer.style.pixelTop == orgnY)
{
EndMove();
}
}
//
位于目标左下
else if(cloneLayer.style.pixelLeft <= orgnX && cloneLayer.style.pixelTop >= orgnY)
{
cloneLayer.style.pixelLeft += stepX;
cloneLayer.style.pixelTop -= stepY;
if(cloneLayer.style.pixelLeft > orgnX)
{
stepX = 1;
}
if(cloneLayer.style.pixelTop < orgnY)
{
stepY = 1;
}
if(cloneLayer.style.pixelLeft == orgnX)
{
stepX = 0;
}
if(cloneLayer.style.pixelTop == orgnY)
{
stepY = 0;
}
if(cloneLayer.style.pixelLeft == orgnX && cloneLayer.style.pixelTop == orgnY)
{
EndMove();
}
}
//
位于目标右上
else if(cloneLayer.style.pixelLeft >= orgnX && cloneLayer.style.pixelTop <= orgnY)
{
cloneLayer.style.pixelLeft -= stepX;
cloneLayer.style.pixelTop += stepY;
if(cloneLayer.style.pixelLeft < orgnX)
{
stepX = 1;
}
if(cloneLayer.style.pixelTop > orgnY)
{
stepY = 1;
}
if(cloneLayer.style.pixelLeft == orgnX)
{
stepX = 0;
}
if(cloneLayer.style.pixelTop == orgnY)
{
stepY = 0;
}
if(cloneLayer.style.pixelLeft == orgnX && cloneLayer.style.pixelTop == orgnY)
{
EndMove();
}
}
//
位于目标右上
else if(cloneLayer.style.pixelLeft >= orgnX && cloneLayer.style.pixelTop >= orgnY)
{
cloneLayer.style.pixelLeft -= stepX;
cloneLayer.style.pixelTop -= stepY;
if(cloneLayer.style.pixelLeft < orgnX)
{
stepX = 1;
}
if(cloneLayer.style.pixelTop < orgnY)
{
stepY = 1;
}
if(cloneLayer.style.pixelLeft == orgnX)
{
stepX = 0;
}
if(cloneLayer.style.pixelTop == orgnY)
{
stepY = 0;
}
if(cloneLayer.style.pixelLeft == orgnX && cloneLayer.style.pixelTop == orgnY)
{
EndMove();
}
}
//
到达目标
else
{
EndMove();
}
}
//
停止返回动画
function
EndMove()
{
sourceLayer.style.pixelLeft = orgnX;
sourceLayer.style.pixelTop = orgnY;
cloneLayer.style.pixelLeft = orgnX;
cloneLayer.style.pixelTop = orgnY;
cloneLayer.className = "docked";
clearInterval(back);
}
//
主拖拽函数
function
startDraging(inAim,inSource,inClone,initAimX,initAimY,initOrgnX,initOrgnY)
{
getLayer(inAim,inSource,inClone)
initDrag(initAimX,initAimY,initOrgnX,initOrgnY);
sourceLayer.onmousedown = BeforeDrag;
document.onmousemove = OnDrag; //
这里如果用cloneLayer,在拖拽中会选中cloneLayer里面内容,进而出现一些bug...
cloneLayer.onmouseup = EndDrag;
}
//
调用
startDraging("aim","sourceLayer","cloneLayer",300,200,20,20);
//-->
</
script
>
</
body
>
</
html
>
需要注意的是:
一.html里面对于div的定义需要有三个. 三个层都必须定义style的position为absolute,以便控制位置
1.目标层(aim),主要作用是定义拖拽生效的位置.
2.拖拽源(sourceLayer).注意设置属性unselectable = "off"(这里比较奇怪,设置成on范围会在拖拽过程中选中层内容)
3.用于复制的层(cloneLayer).
二.函数的调用
startDraging参数解释:
initAim 目标层名称 initSource 拖拽源名称 initClone 用于复制的层的名称
initAimX 目标层x轴坐标 initAimY 目标层y轴坐标 initOrgnX 拖拽源x坐标 initOrgnY 拖拽源Y轴坐标
仅IE里面测试通过.代码里面添加了注释.可以在拖拽源到达目标之后添加写xml的操作.进而记录用户自定义页面排版的数据.对于返回动画的算法还不是很满意.希望各位多多提些建议.以便完善.小弟当前致力于开发一套基于asp.net2.0的ajax控件.希望多多交流.
ps:偶的博客园的第一篇文章.望多多支持.
需要注意的是:
一.html里面对于div的定义需要有三个. 三个层都必须定义style的position为absolute,以便控制位置
1.目标层(aim),主要作用是定义拖拽生效的位置.
2.拖拽源(sourceLayer).注意设置属性unselectable = "off"(这里比较奇怪,设置成on范围会在拖拽过程中选中层内容)
3.用于复制的层(cloneLayer).
二.函数的调用
startDraging参数解释:
initAim 目标层名称 initSource 拖拽源名称 initClone 用于复制的层的名称
initAimX 目标层x轴坐标 initAimY 目标层y轴坐标 initOrgnX 拖拽源x坐标 initOrgnY 拖拽源Y轴坐标
仅IE里面测试通过.代码里面添加了注释.可以在拖拽源到达目标之后添加写xml的操作.进而记录用户自定义页面排版的数据.对于返回动画的算法还不是很满意.希望各位多多提些建议.以便完善.小弟当前致力于开发一套基于asp.net2.0的ajax控件.希望多多交流.
ps:偶的博客园的第一篇文章.望多多支持.