<!--
【程序原理】
这里以SimpleDrag为例说一下基本原理。
首先初始化程序中要一个拖放对象:
this.Drag = $(drag);
还要两个参数在开始时记录鼠标相对拖放对象的坐标:
this._x = this._y = 0;
还有两个事件对象函数用于添加移除事件:
this._fM = BindAsEventListener(this, this.Move);
this._fS = Bind(this, this.Stop);
分别是拖动程序和停止拖动程序。
拖放对象的position必须是absolute绝对定位:
this.Drag.style.position = "absolute";
最后把Start开始拖放程序绑定到拖放对象mousedown事件:
addEventHandler(this.Drag, "mousedown", BindAsEventListener(this, this.Start));
鼠标在拖放对象按住,就会触发Start程序,主要是用来准备拖动,在这里记录鼠标相对拖放对象的坐标:
this._x = oEvent.clientX - this.Drag.offsetLeft;
this._y = oEvent.clientY - this.Drag.offsetTop;
并把_fM拖动程序和_fS停止拖动程序分别绑定到document的mousemove和mouseup事件:
addEventHandler(document, "mousemove", this._fM);
addEventHandler(document, "mouseup", this._fS);
绑定到document可以保证事件在整个窗口文档中都有效。
当鼠标在文档上移动时,就会触发Move程序了,这里就是实现拖动的程序。
通过现在鼠标的坐标值跟开始拖动时鼠标相对的坐标值的差就可以得到拖放对象应该设置的left和top了:
this.Drag.style.left = oEvent.clientX - this._x + "px";
this.Drag.style.top = oEvent.clientY - this._y + "px";
最后放开鼠标后就触发Stop程序结束拖放。
这里的主要作用是把Start程序中给document添加的事件移除:
removeEventHandler(document, "mousemove", this._fM);
removeEventHandler(document, "mouseup", this._fS);
这样一个简单的拖放程序就做好了,下面说说其他扩展和细节部分。
【拖放锁定】
锁定分三种,分别是:水平方向锁定(LockX)、垂直方向锁定(LockY)、完全锁定(Lock)。
这个比较简单,水平和垂直方向的锁定只要在Move判断是否锁定再设置left和top就行,如果是完全锁定就直接返回。
if(!this.LockX){ this.Drag.style.left = ...; }
if(!this.LockY){ this.Drag.style.top = ...; }
【触发对象】
触发对象是用来触发拖放程序的。有的时候不需要整个拖放对象都用来触发,这时就需要触发对象了。
使用了触发对象后,进行移动的还是拖放对象,只是用触发对象来触发拖放(一般的使用是把触发对象放到拖放对象里面)。
【范围限制】
要设置范围限制必须先把Limit设为true。范围限制分两种,分别是固定范围和容器范围限制,主要在Move程序中设置。
原理是当比较的值超过范围时,修正left和top要设置的值使拖放对象能保持在设置的范围内。
【固定范围限制】
容器范围限制就是指定上下左右的拖放范围。
各个属性的意思是:
上(mxTop):top限制;
下(mxBottom):top+offsetHeight限制;
左(mxLeft):left限制;
右(mxRight):left+offsetWidth限制。
如果范围设置不正确,可能导致上下或左右同时超过范围的情况,所以要在Start程序中进行修正:
this.mxRight = Math.max(this.mxRight, this.mxLeft + this.Drag.offsetWidth);
this.mxBottom = Math.max(this.mxBottom, this.mxTop + this.Drag.offsetHeight);
其中mxLeft+offsetWidth和mxTop+offsetHeight分别是mxRight和mxBottom的最小范围值。
根据范围参数修正移动参数:
iLeft = Math.max(Math.min(iLeft, mxRight - this.Drag.offsetWidth), mxLeft);
iTop = Math.max(Math.min(iTop, mxBottom - this.Drag.offsetHeight), mxTop);
对于左边上边要取更大的值,对于右边下面就要取更小的值。
【容器范围限制】
容器范围限制的意思就是把范围限制在一个容器_mxContainer内。
要注意的是拖放对象必须包含在_mxContainer中,因为程序中是使用相对定位来设置容器范围限制的(如果是在容器外就要用绝对定位,这样处理就比较麻烦了),还有就是容器空间要比拖放对象大,这个就不用说明了吧。
原理跟固定范围限制差不多,只是范围参数是根据容器的属性的设置的。
当设置了容器,会自动把position设为relative来相对定位:
!this._mxContainer || CurrentStyle(this._mxContainer).position == "relative" || (this._mxContainer.style.position = "relative");
注意relative要在获取offsetLeft和offsetTop即设置_x和_y之前设置,offset才能正确获取值。
由于是相对定位,对于容器范围来说范围参数上下左右的值分别是0、clientHeight、0、clientWidth。
clientWidth和clientHeight是容器可视部分的宽度和高度(详细参考这里)。
为了容器范围能兼容固定范围的参数,程序中会获取容器范围和固定范围中范围更小的值:
mxLeft = Math.max(mxLeft, 0);
mxTop = Math.max(mxTop, 0);
mxRight = Math.min(mxRight, this._mxContainer.clientWidth);
mxBottom = Math.min(mxBottom, this._mxContainer.clientHeight);
要注意如果在程序执行之前设置过拖放对象的left和top而容器没有设置relative,在自动设置relative时会发生移位现象,所以尽量避免没有设置relative而又设置了拖放对象left和top,才执行程序的情况。
不过也有一个取巧的方法就是设置margin来代替定位(使用margin的话会自动修正,后面说明)。
因为设置相对定位的关系,容器_mxContainer设置过后一般不要取消或修改,否则很容易造成移位异常。
【鼠标捕获】
我在一个拖放实例中看到,即使鼠标移动到浏览器外面,拖放程序依然能够执行,仔细查看后发现是用了setCapture。
鼠标捕获(setCapture)是这个程序的重点,作用是将鼠标事件捕获到当前文档的指定的对象。这个对象会为当前应用程序或整个系统接收所有鼠标事件。
使用很简单:
this._Handle.setCapture();
setCapture捕获以下鼠标事件:onmousedown、onmouseup、onmousemove、onclick、ondblclick、onmouseover和onmouseout。
程序中主要是要捕获onmousemove和onmouseup事件。
msdn的介绍中还说到setCapture有一个bool参数,用来设置在容器内的鼠标事件是否都被容器捕获。
容器就是指调用setCapture的对象,大概意思就是:
参数为true时(默认)容器会捕获容器内所有对象的鼠标事件,即容器内的对象不会触发鼠标事件(跟容器外的对象一样);
参数为false时容器不会捕获容器内对象的鼠标事件,即容器内的对象可以正常地触发事件和取消冒泡。
而对于容器外的鼠标事件无论参数是什么都会被捕获,
可以用下面这个简单的例子测试一下(ie):
<html>
<body onclick="alert(2)">
<div onmousemove="alert(1)">mouseover </div>
<script>document.body.setCapture(); </script>
</body>
</html>
这里的参数是true,一开始body会捕获所有鼠标事件,即使鼠标经过div也不会触发onmousemove事件。
换成false的话,div就可以捕获鼠标事件,就能触发onmousemove事件了。
拖放结束后还要使用releaseCapture释放鼠标,这个可以放在Stop程序中:
this._Handle.releaseCapture();
setCapture是ie的鼠标捕获方法,对于ff也有对应的captureEvents和releaseEvents方法。
但这两个方法只能由window来调用,而且muxrwc说这两个方法在DOM2里已经废弃了,在ff里已经没用了。
不过ff里貌似会自动设置取消鼠标捕获,但具体的情形就不清楚了,找不到一个比较详细的介绍,谁有这方面的资料记得告诉我啊。
下面都是我的猜测,ff的鼠标捕获相当于能自动
没有合适的资源?快使用搜索试试~ 我知道了~
两款JAVASCRIPT拖拽(拖放)
共5个文件
htm:2个
html:2个
js:1个
4星 · 超过85%的资源 需积分: 9 37 下载量 92 浏览量
2008-11-20
11:10:53
上传
评论 1
收藏 17KB RAR 举报
温馨提示
来源于网络,收藏共享。 其中一款还附了原理分析
资源推荐
资源详情
资源评论
收起资源包目录
Drag.rar (5个子文件)
drag_2.html 25KB
SimpleDrag.htm 3KB
tuozhuai.js 16KB
Drag.htm 8KB
tuozhuai.html 5KB
共 5 条
- 1
资源评论
- one_bullet2012-11-28资源不错哈,适合我这样的新手,不过有的地方看不明白呀!
多菜鸟
- 粉丝: 274
- 资源: 8
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功