• 一步一步实现AS3拖放组件


    外话:

    我之前在天地会上发布过一个拖放组件,http://bbs.9ria.com/thread-117535-1-1.html

    应该有人看过吧,那时候年纪轻轻,写了个东西,那时候基本能满足需求
    但是,现在毕业了正式上岗了的我来说,那样的组件简直是弱爆了,无论从代码看还是从设计上来看,随处可见菜鸟特征
     
    现在工作了,从事页游行业,项目组把UI这块包给我了,然后我就开始做了,期间写了一些组件,也包括mornui的一些组件,都是要在游戏中用到的。
    今天要解决的就是拖放组件了,当然首先想到的就是我之前写的那个组件了,但是啊但是,那个组件太单调了啊,向下兼容不好,扩展又不好。
    于是呼,我还是重新写了一个,做拖放其实挺简单的,所以此文仅供参考啊!
     
    开始实现:
    先来看看我做的拖放的demo截图(考虑到呈现简单,我用了as3语言)
     
    左边是橙色框,右边是蓝色框,模拟不同的拖放域,左右不能互相拖放,但是各自域里可以随便拖放!
     
    基本功能就是:
    1. 可以拖
    2. 可以放
    3. 交换,替换,覆盖之类(由拖和放组合完成)
    注:我没有查过有关拖放的文章或者解决方案,只是凭借自己对传统PC操作系统的拖放的使用总结来实现的我们今天开发拖放组件。
     
    一般的拖放操作,都离不开鼠标的各种事件,MouseDown,MouseUp,ROLL_OVER,ROLL_OUT这四个事件,那我们如何组合这四个事件来实现拖放嘞,立即开始!
     
    我简略地画了个图,一般的拖放操作就是这个逻辑顺序。
    结合代码来看:
    为了方便操作,我只用了一个类,包括各种静态变量和静态方法。
    静态变量主要存放的是拖放源、拖放标识和拖放透明图(avatar)
    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

    转载请注明出处:http://www.cnblogs.com/rockyf/p/DragableItem.html

  • 相关阅读:
    最有影响力的计算机视觉会议及期刊论文
    计算机视觉与图像处理方面的顶级期刊
    总结一下国内搞机器学习和数据挖掘的大牛
    戴尔▪卡耐基《人性的弱点》阅读笔记(1)
    Python GUI之tkinter窗口视窗教程大集合(看这篇就够了)
    自控力极差的人如何自救?
    非技术人员也能看懂云计算,大数据,人工智能
    保罗·多兰《设计幸福》阅读笔记
    神经网络浅讲:从神经元到深度学习----以简单循序的方式带你聊聊深度学习
    从机器学习谈起----极好的一篇机器学习全貌入门文章
  • 原文地址:https://www.cnblogs.com/rockyf/p/DragableItem.html
Copyright © 2020-2023  润新知