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