外话:
我之前在天地会上发布过一个拖放组件,http://bbs.9ria.com/thread-117535-1-1.html
- 可以拖
- 可以放
- 交换,替换,覆盖之类(由拖和放组合完成)
public static var avatarContainer:Sprite;
public static var avatarBmp:Bitmap;
public static var isDraging:Boolean;
还需要一个静态方法来初始化拖放类:
public static function init():void{
if(!avatarContainer){
avatarContainer = new Sprite();
avatarContainer.mouseEnabled = false;
avatarBmp = new Bitmap();
avatarContainer.addChild(avatarBmp);
} isDraging = false;
}
然后我们就可以开始写拖放:
在构造方法中初始化变量和侦听鼠标事件
private function init():void{
_accept = false;
dragable = false; _mouseDownPoint = new Point(); addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
addEventListener(MouseEvent.ROLL_OVER, onRollOver);
}
在鼠标按下时,要记录按下的坐标,并侦听stage的鼠标弹起事件,在判断是否支持拖操作后,进行拖操作
protected function onMouseDown(event:MouseEvent):void{
stage.addEventListener(MouseEvent.MOUSE_UP, onStageMouseUp);
if(dragable){
_mouseDownPoint.x = event.localX;
_mouseDownPoint.y = event.localY;
beginDrag();
}
}
开始拖操作,我们要获得一下在拖动时需要呈现的那张图,图可以在子类中重写dragAvatar()方法类获得
在执行拖动前,会执行beforDrag(),我们可以在这里对呈现图进行处理,比如加点透明度之类的
我写的拖放直接使用了as3提供的startDrag,方便快捷!
protected function beginDrag():void{
avatarBmp.bitmapData = dragAvatar;
beforDrag();
if(!stage.contains(avatarContainer)){
stage.addChild(avatarContainer);
} itemSrc = this; var sPoint:Point = this.localToGlobal(new Point(mouseX, mouseY));
avatarContainer.x = sPoint.x - _mouseDownPoint.x;
avatarContainer.y = sPoint.y - _mouseDownPoint.y; avatarContainer.startDrag(); isDraging = true;
} protected function get dragAvatar():BitmapData{
return ObjectUtils.cloneDisplayObject(this);
} protected function beforDrag():void{
avatarBmp.alpha = 0.8;
}
就此,拖的过程就搞定了,接下来的就是放操作了。
其实拖放的大头主要在放的操作上,因为拖操作决定的只是数据源,而放操作则会涉及到各种逻辑处理
放操作会在ROLL_OVER事件开始,当鼠标拖着东西进入目标对象时,会触发dragEnter()方法,然后触发addEffect()方法,在移出时会触发removeEffect()方法
问:什么是addEffect()和removeEffect()方法?
答:在放操作的时候,如果目标对象不让放操作或者拖放源不符合条件,那放操作将不给予通行,我在拖进时加了一个dragEnter()方法,返回值就是是否准许放操作,根据返回值,来添加一些特效,
当左边拖到右边时,是不被准许,所以我加了个红色外发光的特效
当右边的拖到右边时,准许拖放,所以我加了个蓝色外发光的特效
protected function dragEnter(itemSrc:DragableItem):Boolean{
trace("dragEnter"); return true;
}
protected function onRollOver(event:MouseEvent):void{
addEventListener(MouseEvent.ROLL_OUT, onRollOut); if(isDraging && itemSrc != this){
addEffect(_accept = dragEnter(itemSrc));
}
} protected function onRollOut(event:MouseEvent):void{
removeEventListener(MouseEvent.ROLL_OUT, onRollOut); if(isDraging && itemSrc != this){
removeEffect();
}
}
最后就是两个MOUSE_UP事件了
protected function onMouseUp(event:MouseEvent):void{
if(_accept){
dragDrop(itemSrc);
} endDrag();
isDraging = false;
if(itemSrc != this){
removeEffect();
}
} protected function onStageMouseUp(event:MouseEvent):void{
stage.removeEventListener(MouseEvent.MOUSE_UP, onStageMouseUp);
if(isDraging){
endDrag();
isDraging = false;
if(itemSrc != this){
removeEffect();
}
}
}
前者是自身的鼠标弹起,后者是stage的鼠标弹起
在自身的鼠标弹起事件,如果放操作被准许,那么就实行dragDrop()方法,最后结束拖放和移除特效
在stage的鼠标弹起事件中也做一些收尾操作,当然,我的代码有些冗余了
而后要实现的交换,替换,覆盖等操作,都交给子类的dragDrop()方法来实现就行
比如我写的一个子类中,判断左右域不能互拖的限制:
override protected function dragEnter(itemSrc:DragableItem):Boolean
{
var _itemSrc:DragItemSimple = itemSrc as DragItemSimple;
return int(_itemSrc.index / 10) == int(index / 10);
}
我只是判断索引的十位数是否相等,相等就返回true,就是可拖放,不相等就返回false,就是不可拖放。
总结:
做拖放也不是很难,只要理清思路。
说了那么多(其实是代码贴得多了点,o(∩_∩)o ),源码提供下载:
下载点:DragableItem