我们的山寨Starling版本将会在这里停止更新了,主要还是由于时间比较有限,而且我们的山寨版本也很好的完成了他的任务“了解Starling的核心渲染”,接下来的Starling解析我们将会直接阅读Starling的源码来了解其它的内部运行方式。
Touch事件体系无疑是除了核心渲染外最重要的东西了,我们笔记中的Touch事件体系是基于Starling v1.1来解读的。
Touch事件体系简介:
在Starling的承继关系里是没有InteractiveObject类,因此所有的显示对象都默认具有交互功能。也就是说DisplayObject是定义了交互行为的。
我们看看主要的类的功能:
- TouchEvent:Touch事件类,Starling中将原生的鼠标和触摸事件都统一封装成TouchEvent类,这样可以保证PC开发和移动端运行时的一致性,而不同于原生事件,TouchEvent的事件类型仅有一个“TouchEvent.TOUCH”。
- Touch:一个Touch对象包含了在屏幕上的一个手指或鼠标的相关详细信息,如果是多点触控,则会存在多个Touch对象。
- TouchPhase:因为TouchEvent只有一个事件类型“TOUCH”,那么我们要区分具体的情况(按下、移动和弹起等)就需要使用Touch对象的phase属性了,而TouchPhase则定义了phase属性存在的值。
- TouchProcessor:Touch事件体系核心处理类,也是我们接下来要核心解读的类。
- TouchMarker:内部使用,PC模拟多点触控时的显示对象。
Touch事件处理流程:
Starling中持有一个TouchProcessor类的实例“mTouchProcessor”,该类用来统一处理所有的Touch事件。
还需要注意的一点是,Touch事件会有"延迟",因为Starling捕获到原生Flash层的事件之后,不会马上派发给侦听Starling事件的对象,而是先发送内部的“队列”里面,然后根据帧频,进行集中处理。不过一般我们的帧频不会设置的太小,这个延迟对用户基本没有影响。
原生事件注册:
Starling类启动时会对Stage进行事件注册:
1 public function Starling(xxx) 2 { 3 ... 4 // register touch/mouse event handlers 5 for each (var touchEventType:String in touchEventTypes) 6 stage.addEventListener(touchEventType, onTouch, false, 0, true); 7 ... 8 } 9 10 private function get touchEventTypes():Array 11 { 12 return Mouse.supportsCursor || !multitouchEnabled ? 13 [ MouseEvent.MOUSE_DOWN, MouseEvent.MOUSE_MOVE, MouseEvent.MOUSE_UP ] : 14 [ TouchEvent.TOUCH_BEGIN, TouchEvent.TOUCH_MOVE, TouchEvent.TOUCH_END ]; 15 }
我们可以看到会根据是否支持鼠标和是否开启多点触控来选择注册的事件类型,而所有事件的处理都交给onTouch方法。
onTouch方法处理:
1 private function onTouch(event:Event):void 2 { 3 if (!mStarted) return; 4 5 var globalX:Number; 6 var globalY:Number; 7 var touchID:int; 8 var phase:String; 9 10 // figure out general touch properties 11 if (event is MouseEvent) 12 { 13 var mouseEvent:MouseEvent = event as MouseEvent; 14 globalX = mouseEvent.stageX; 15 globalY = mouseEvent.stageY; 16 touchID = 0; 17 18 // MouseEvent.buttonDown returns true for both left and right button (AIR supports 19 // the right mouse button). We only want to react on the left button for now, 20 // so we have to save the state for the left button manually. 21 if (event.type == MouseEvent.MOUSE_DOWN) mLeftMouseDown = true; 22 else if (event.type == MouseEvent.MOUSE_UP) mLeftMouseDown = false; 23 } 24 else 25 { 26 var touchEvent:TouchEvent = event as TouchEvent; 27 globalX = touchEvent.stageX; 28 globalY = touchEvent.stageY; 29 touchID = touchEvent.touchPointID; 30 } 31 32 // figure out touch phase 33 switch (event.type) 34 { 35 case TouchEvent.TOUCH_BEGIN: phase = TouchPhase.BEGAN; break; 36 case TouchEvent.TOUCH_MOVE: phase = TouchPhase.MOVED; break; 37 case TouchEvent.TOUCH_END: phase = TouchPhase.ENDED; break; 38 case MouseEvent.MOUSE_DOWN: phase = TouchPhase.BEGAN; break; 39 case MouseEvent.MOUSE_UP: phase = TouchPhase.ENDED; break; 40 case MouseEvent.MOUSE_MOVE: 41 phase = (mLeftMouseDown ? TouchPhase.MOVED : TouchPhase.HOVER); break; 42 } 43 44 // move position into viewport bounds 45 globalX = mStage.stageWidth * (globalX - mViewPort.x) / mViewPort.width; 46 globalY = mStage.stageHeight * (globalY - mViewPort.y) / mViewPort.height; 47 48 // enqueue touch in touch processor 49 mTouchProcessor.enqueue(touchID, phase, globalX, globalY); 50 }