外话:

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

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

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

一步一步实现AS3拖放组件的更多相关文章

  1. C#进阶系列——一步一步封装自己的HtmlHelper组件:BootstrapHelper(三:附源码)

    前言:之前的两篇封装了一些基础的表单组件,这篇继续来封装几个基于bootstrap的其他组件.和上篇不同的是,这篇的有几个组件需要某些js文件的支持. 本文原创地址:http://www.cnblog ...

  2. C#进阶系列——一步一步封装自己的HtmlHelper组件:BootstrapHelper

    前言:之前学习过很多的Bootstrap组件,博主就在脑海里构思:是否可以封装一套自己Bootstrap组件库呢.再加上看到MVC的Razor语法里面直接通过后台方法输出前端控件的方式,于是打算仿照H ...

  3. 一步一步学Silverlight 2系列(5):实现简单的拖放功能

    述 Silverlight 2 Beta 1版本发布了,无论从Runtime还是Tools都给我们带来了很多的惊喜,如支持框架语言Visual Basic, Visual C#, IronRuby, ...

  4. 大流量网站性能优化:一步一步打造一个适合自己的BigRender插件

    BigRender 当一个网站越来越庞大,加载速度越来越慢的时候,开发者们不得不对其进行优化,谁愿意访问一个需要等待 10 秒,20 秒才能出现的网页呢? 常见的也是相对简单易行的一个优化方案是 图片 ...

  5. 一步一步跟我学DeviceOne开发 - 仿微信应用(一,二,三)

    这是一个系列的文档,长期目标是利用DeviceOne开发一些目前使用广泛的优质手机应用,我们会最大化的实现这些应用的每一个功能和细节,不只停留在简单的UI模仿和Demo阶段,而是一个基本可以使用的实际 ...

  6. 一步一步教你如何在linux下配置apache+tomcat(转)

    一步一步教你如何在linux下配置apache+tomcat   一.安装前准备. 1.   所有组件都安装到/usr/local/e789目录下 2.   解压缩命令:tar —vxzf 文件名(. ...

  7. 一步一步理解Paxos算法

    一步一步理解Paxos算法 背景 Paxos 算法是Lamport于1990年提出的一种基于消息传递的一致性算法.由于算法难以理解起初并没有引起人们的重视,使Lamport在八年后重新发表到 TOCS ...

  8. 跟我一步一步开发自己的Openfire插件

    http://www.blogjava.net/hoojo/archive/2013/03/07/396146.html 跟我一步一步开发自己的Openfire插件 这篇是简单插件开发,下篇聊天记录插 ...

  9. 一步一步深入spring(2)-三种方式来实例化bean

    在一步一步深入spring(1)--搭建和测试spring的开发环境中提到了一种实例化bean的方式,也是最基本的使用构造器实例化bean 1.使用构造器实例化bean:这是最简单的方式,Spring ...

随机推荐

  1. python交换两个变量的值,一句代码搞定

    a = 10 b = 20 # 不需要中间变量,一步搞定 a, b = b, a

  2. 初学swift笔记 枚举(七)

    import Foundation /* 枚举 语法结构 enum 类型 { case 值 } */ //定义一个枚举 写法1 enum LiuShiQun { case Name case Age ...

  3. Oracle EBS-SQL (OM-3):销售连接停靠站时冲减库存出错处理.sql

    DELETE FROM INV.MTL_RESERVATIONS MRWHERE EXISTS (SELECT 1 FROM WSH.WSH_DELIVERY_ASSIGNMENTS WDA      ...

  4. Java Script 中 ==(Equal) 和 === (Identity Equal) 的区别和比较算法逻辑

    判断两个变量是否相等在任何编程语言中都是非常重要的功能. JavaScript 提供了 == 和 === 两种判断两个变量是否相等的运算符,但我们开始学习的时候 JavaScript 的时候,就被一遍 ...

  5. 新建Android项目的时候,选择SDK的区别

    选择新建一个Android项目时候,出现MiniMum Required SDK.Target SDK.Compile With.Theme,如下所示,分别是什么意思呢? MinMum Require ...

  6. 一篇memcache基础教程

    Memcache是什么Memcache是danga.com的一个项目,最早是为 LiveJournal 服务的,目前全世界不少人使用这个缓存项目来构建自己大负载的网站,来分担数据库的压力.它可以应对任 ...

  7. Boost程序库完全开发指南——深入C++“准”标准库(第3版)

    内容简介  · · · · · · Boost 是一个功能强大.构造精巧.跨平台.开源并且完全免费的C++程序库,有着“C++‘准’标准库”的美誉. Boost 由C++标准委员会部分成员所设立的Bo ...

  8. 百度地图V2.0实践项目开发工具类bmap.util.js V1.4

    /** * 百度地图使用工具类-v2.0(大眾版) * * @author boonya * @date 2013-7-7 * @address Chengdu,Sichuan,China * @em ...

  9. Google地图轨迹回放模拟

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  10. poj 2425 A Chess Game_sg函数

    题意:给你一个有向无环图,再给你图上的棋子,每人每次只能移动一个棋子,当轮到你不能移动棋子是就输了,棋子可以同时在一个点 比赛时就差这题没ak,做了几天博弈终于搞懂了. #include <io ...