1 MouseManager:
2 private function check(sp:Sprite, mouseX:Number, mouseY:Number, callBack:Function):Boolean {
3 this._point.setTo(mouseX, mouseY);
4 sp.fromParentPoint(this._point);
5 mouseX = this._point.x;
6 mouseY = this._point.y;
7
8 //如果有裁剪,则先判断是否在裁剪范围内
9 var scrollRect:Rectangle = sp.scrollRect;
10 if (scrollRect) {
11 _rect.setTo(scrollRect.x, scrollRect.y, scrollRect.width, scrollRect.height);
12 if (!_rect.contains(mouseX, mouseY)) return false;
13 }
14
15 //先判定子对象是否命中
16 if (!disableMouseEvent) {
17 //优先判断父对象
18 //默认情况下,hitTestPrior=mouseThrough=false,也就是优先check子对象
19 //$NEXTBIG:下个重大版本将sp.mouseThrough从此逻辑中去除,从而使得sp.mouseThrough只负责目标对象的穿透
20 if (sp.hitTestPrior && !sp.mouseThrough && !hitTest(sp, mouseX, mouseY)) {
21 return false;
22 }
23 for (var i:int = sp._childs.length - 1; i > -1; i--) { //倒叙遍历,从外向内检测,如果检测到则跳过内部检测
24 var child:Sprite = sp._childs[i];
25 //只有接受交互事件的,才进行处理
26 if (!child.destroyed && child.mouseEnabled && child.visible) {
27 if (check(child, mouseX, mouseY, callBack)) return true;
28 }
29 }
30 }
31
32 //避免重复进行碰撞检测,考虑了判断条件的命中率。
33 var isHit:Boolean = (sp.hitTestPrior && !sp.mouseThrough && !disableMouseEvent) ? true : hitTest(sp, mouseX, mouseY);
34
35 if (isHit) {
36 _target = sp;
37 callBack.call(this, sp);
38 } else if (callBack === onMouseUp && sp === _stage) {
39 //如果stage外mouseUP
40 _target = _stage;
41 callBack.call(this, _target);
42 }
43
44 return isHit;
45 }
46
47 private function hitTest(sp:Sprite, mouseX:Number, mouseY:Number):Boolean {
48 var isHit:Boolean = false;
49 if (sp.scrollRect) {
50 mouseX -= sp.scrollRect.x;
51 mouseY -= sp.scrollRect.y;
52 }
53 if (sp.hitArea is HitArea) {
54 return sp.hitArea.isHit(mouseX, mouseY);
55 }
56 if (sp.width > 0 && sp.height > 0 || sp.mouseThrough || sp.hitArea) {
57 //判断是否在矩形区域内
58 if (!sp.mouseThrough) {
59 var hitRect:Rectangle = this._rect;
60 if (sp.hitArea) hitRect = sp.hitArea;
61 else hitRect.setTo(0, 0, sp.width, sp.height); //坐标已转换为本地坐标系
62 isHit = hitRect.contains(mouseX, mouseY);
63 } else {
64 //如果可穿透,则根据子对象实际大小进行碰撞
65 isHit = sp.getGraphicBounds().contains(mouseX, mouseY);
66 }
67 }
68 return isHit;
69 }
70
71 /**
72 * 执行事件处理。
73 */
74 public function runEvent():void {
75 var len:int = _eventList.length;
76 if (!len) return;
77
78 var _this:MouseManager = this;
79 var i:int = 0,j:int,n:int,touch:*;
80 while (i < len) {
81 var evt:* = _eventList[i];
82
83 if (evt.type !== 'mousemove') _prePoint.x = _prePoint.y = -1000000;
84
85 switch (evt.type) {
86 case 'mousedown':
87 _touchIDs[0] = _id++;
88 if (!_isTouchRespond) {
89 _this._isLeftMouse = evt.button === 0;
90 _this.initEvent(evt);
91 _this.check(_this._stage, _this.mouseX, _this.mouseY, _this.onMouseDown);
92 } else
93 _isTouchRespond = false;
94 break;
95 case 'mouseup':
96 _this._isLeftMouse = evt.button === 0;
97 _this.initEvent(evt);
98 _this.check(_this._stage, _this.mouseX, _this.mouseY, _this.onMouseUp);
99 break;
100 case 'mousemove':
101 if ((Math.abs(_prePoint.x - evt.clientX) + Math.abs(_prePoint.y - evt.clientY)) >= mouseMoveAccuracy) {
102 _prePoint.x = evt.clientX;
103 _prePoint.y = evt.clientY;
104 _this.initEvent(evt);
105 _this.check(_this._stage, _this.mouseX, _this.mouseY, _this.onMouseMove);
106 // _this.checkMouseOut();
107 }
108 break;
109 case "touchstart":
110 _isTouchRespond = true;
111 _this._isLeftMouse = true;
112 var touches:Array = evt.changedTouches;
113 for (j = 0, n = touches.length; j < n; j++) {
114 touch = touches[j];
115 //是否禁用多点触控
116 if (multiTouchEnabled || isNaN(_curTouchID)) {
117 _curTouchID = touch.identifier;
118 //200次点击清理一下id资源
119 if (_id % 200 === 0) _touchIDs = {};
120 _touchIDs[touch.identifier] = _id++;
121 _this.initEvent(touch, evt);
122 _this.check(_this._stage, _this.mouseX, _this.mouseY, _this.onMouseDown);
123 }
124 }
125
126 break;
127 case "touchend":
128 case "touchcancel":
129 _isTouchRespond = true;
130 _this._isLeftMouse = true;
131 var touchends:Array = evt.changedTouches;
132 for (j = 0, n = touchends.length; j < n; j++) {
133 touch = touchends[j];
134 //是否禁用多点触控
135 if (multiTouchEnabled || touch.identifier == _curTouchID) {
136 _curTouchID = NaN;
137 _this.initEvent(touch, evt);
138 var isChecked:Boolean;
139 isChecked = _this.check(_this._stage, _this.mouseX, _this.mouseY, _this.onMouseUp);
140 if (!isChecked)
141 {
142 _this.onMouseUp(null);
143 }
144 }
145 }
146
147 break;
148 case "touchmove":
149 var touchemoves:Array = evt.changedTouches;
150 for (j = 0, n = touchemoves.length; j < n; j++) {
151 touch = touchemoves[j];
152 //是否禁用多点触控
153 if (multiTouchEnabled || touch.identifier == _curTouchID) {
154 _this.initEvent(touch, evt);
155 _this.check(_this._stage, _this.mouseX, _this.mouseY, _this.onMouseMove);
156 }
157 }
158 break;
159 case "wheel":
160 case "mousewheel":
161 case "DOMMouseScroll":
162 _this.checkMouseWheel(evt);
163 break;
164 case "mouseout":
165 //_this._stage.event(Event.MOUSE_OUT, _this._event.setTo(Event.MOUSE_OUT, _this._stage, _this._stage));
166 TouchManager.I.stageMouseOut();
167 break;
168 case "mouseover":
169 _this._stage.event(Event.MOUSE_OVER, _this._event.setTo(Event.MOUSE_OVER, _this._stage, _this._stage));
170 break;
171 }
172 i++;
173 }
174 _eventList.length = 0;
175 }
176 }
177 TouchManager
178 /**
179 * 派发事件。
180 * @param eles 对象列表。
181 * @param type 事件类型。
182 * @param touchID (可选)touchID,默认为0。
183 */
184 private function sendEvents(eles:Array, type:String, touchID:int = 0):void {
185 var i:int, len:int;
186 len = eles.length;
187 _event._stoped = false;
188 var _target:*;
189 _target = eles[0];
190 var tE:Sprite;
191 for (i = 0; i < len; i++) {
192 tE = eles[i];
193 if (tE.destroyed) return;
194 tE.event(type, _event.setTo(type, tE, _target));
195 if (_event._stoped)
196 break;
197 }
198 }
199
200 /**
201 * 获取对象列表。
202 * @param start 起始节点。
203 * @param end 结束节点。
204 * @param rst 返回值。如果此值不为空,则将其赋值为计算结果,从而避免创建新数组;如果此值为空,则创建新数组返回。
205 * @return Array 返回节点列表。
206 */
207 private function getEles(start:Node, end:Node = null, rst:Array = null):Array {
208 if (!rst) {
209 rst = [];
210 } else {
211 rst.length = 0;
212 }
213 while (start && start != end) {
214 rst.push(start);
215 start = start.parent;
216 }
217 return rst;
218 }