Javascript教程:研究拖放效果
来源:  时间:2008-12-2

完全教程网热荐!Javascript教程!很久,但很不错!要有点耐心!

清除选择

ie在设置setCapture之后内容选择都会被禁止,但也因此不会清除在设置之前就已经选择的内容,而且设置之后也能通过其他方式选择内容,
例如用ctrl+a来选择内容。
ps:onkeydown、onkeyup和onkeypress事件不会受到鼠标捕获影响。
而ff在mousedown时就能清除原来选择的内容,但拖动鼠标,ctrl+a时还是会继续选择内容。
不过在丢弃了系统默认动作之后,这样的选择并不会对拖放操作造成影响,这里设置主要还是为了更好的体验。

以前我用禁止拖放对象被选择的方法来达到目的,即ie中设置拖放对象的onselectstart返回false,在ff中设置样式MozUserSelect(css:-moz-user-select)为none。
但这种方法只能禁止拖放对象本身被选择,后来找到个更好的方法清除选择,不但不影响拖放对象的选择效果,还能对整个文档进行清除:

ie: document.selection.empty()
ff: window.getSelection().removeAllRanges()
为了防止在拖放过程中选择内容,所以把它放到Move程序中,下面是兼容的写法:

window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();

margin

还有一个情况,当拖放对象设置了margin,那么拖放的时候就会错位(给SimpleDrag的拖放对象设置margin就可以测试)。
原因是在Start程序设置_x和_y时是使用offset获取的,而这个值是包括margin的,所以在设置left和top之前要减去这个margin。
但如果在Start程序中就去掉margin那么在Move程序中设置范围限制时就会计算错误,
所以最好是在Start程序中获取值:

this._marginLeft = parseInt(CurrentStyle(this.Drag).marginLeft) || 0;
this._marginTop = parseInt(CurrentStyle(this.Drag).marginTop) || 0;

其中CurrentStyle是用来获取最终样式,详细看这里的最终样式部分。

在Move程序中设置值:

this.Drag.style.left = iLeft - this._marginLeft + "px";
this.Drag.style.top = iTop - this._marginTop + "px";

要注意margin要在范围修正只后再设置,否则会错位。

【透明背景bug】

在ie有一个透明背景bug(不知算不算bug),可以用下面的代码测试:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<body>
<div onmousedown="alert(1)" style="border:10px solid #C4E3FD; width:50px; height:50px;position:absolute;"> </div>
</body>
</html>


会发现背景点击触发不了事件,不过点击边框的话还是可以触发。
为什么呢?再用下面的代码测试:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<body style="border:1px solid #FF0000;">
<style>div{width:100px; height:100px; border:1px solid #000;} </style>
<div style="position:relative;">
<div onclick="alert(1)" style="border-color:#00f;margin:50px;"> </div>
<div onclick="alert(2)" style="border-color:#6f0;position:absolute;top:50px;"> </div>
</div>
</body>
</html>


应该能看出个大概了,下面两个div超出body(即超出红色框)的部分就触发不了事件。
也就是说当触发事件的点,在body以外,而背景又是透明的,那么就会误认为触发点是在了body外空白的地方,所以触发不了事件。
那解决的方法就是,使事件触发点保持在body内,或者设置一个非透明背景。

那程序中只要给拖放对象设一个背景色就可以解决了,但有时需求正好是要透明(例如切割效果),那怎么办呢?
首先想到的是加上背景色后设置完全透明,但这样连边框,容器内的对象等都完全透明了,这个不好。
我想到的一个解决方法是在容器里面加一个层,覆盖整个容器,并设置背景色和完全透明:

with(this._Handle.appendChild(document.createElement("div")).style){
width = height = "100%"; backgroundColor = "#fff"; filter = "alpha(opacity:0)";
}


当发现程序有这个bug出现,把程序可选参数Transparent设为true就会自动插入这样一个层了。
各位如果有更好的方法请多多指点。

暂时就研究到这里,不过还有iframe,滚屏等这些还没考虑到,等以后有需要了再来研究拉。

>> 相关文章