首先來比較一下Starling的TouchEvent跟native的TiuchEvent,Starling只有一個TouchEvent.TOUCH,而不像native有分TouchEvent.TOUCH_BEGIN、TouchEvent.TOUCH_MOVE、TouchEvent.TOUCH_END等等。除此之外,整個Touch的概念是一樣的。
Starling裡面,當DisplayObject與滑鼠或手指產生互動時,就會發出TouchEvent.Touch。而這時候Starling會產生Touch物件來記錄滑鼠或手指的"點",而每個點依照它與DisplayObject互動的狀況可分為不同的TouchPhase:點下去為TouchPhase.BEGAN,放開為TouchPhase.ENDED,經過時為TouchPhase.HOVER,停住不動為TouchPhase.STATIONARY。用法是DisplayObject監聽TouchEvent.TOUCH,然後在event handler部分,假設我們接收到e為TouchEvent,可使用e.getTouch()來取得滑鼠或第一點的Touch,若需要偵測多點則使用e.getTouches()取得一個Touch Vector。可以在e.getTouch()的第二個參數線定要取得的TouchPhase,也可以取得後再從touch.phase來判斷。
我們來寫個練習,使用Image代替上個範例的Button,利用TouchEvent做出Mouse Over與Mouse Out的效果:
public class Game4 extends Sprite { private var _container:Sprite; private var _msgText:TextField; private var _btnTexture:Texture; private var _btnDownTexture:Texture; private var _btnHoverTexture:Texture; [Embed(source = "/assets/btnBg.png")]//embed Button一般狀態的圖 private static const BtnBitmap:Class; [Embed(source = "/assets/btnDownBg.png")]//embed Button壓下的圖 private static const BtnDownBitmap:Class; [Embed(source = "/assets/btnHoverBg.png")]//embed Button Hover(Mouse Over)的圖 private static const BtnHoverBitmap:Class; public function Game4() { super(); addEventListener(Event.ADDED_TO_STAGE, init); } private function init(e:Event):void { removeEventListener(Event.ADDED_TO_STAGE, init); _container = new Sprite(); addChild(_container); addChild(new Stats()); var menu:Sprite = new Sprite(); menu.x = 100; menu.y = 30; _container.addChild(menu); _msgText = new TextField(300, 20, "No Button Triggered.", "Arial", 14, 0xFF0000, true); _msgText.x = 100; _msgText.y = 80; _msgText.hAlign = HAlign.LEFT; _container.addChild(_msgText); _btnTexture = Texture.fromBitmap(new BtnBitmap());//Button一般狀態的Texture _btnDownTexture = Texture.fromBitmap(new BtnDownBitmap());//Button壓下的Texture _btnHoverTexture = Texture.fromBitmap(new BtnHoverBitmap());//Button Hover(Mouse Over)的Texture var btnTexts:Vector.<string> = new Vector.<string>(); btnTexts.push("About"); btnTexts.push("Works"); btnTexts.push("Video"); btnTexts.push("Contact"); var btnNum:uint = btnTexts.length; var button:Image;//改用Image來當Button for (var i:int = 0; i < btnNum; i++) { button = new Image(_btnTexture); button.x = i * 150; button.name = "btn" + btnTexts[i]; menu.addChild(button); } menu.addEventListener(TouchEvent.TOUCH, onTouch);//TouchEvent預設會bubble,所以menu加監聽就可以了 } private function onTouch(e:TouchEvent):void { var touch:Touch;//滑鼠或手指產生的Touch var target:Image = Image(e.target);//真正發出事件的Image touch = e.getTouch(this, TouchPhase.BEGAN);//針對BEGAN處理 if(touch) { target.texture = _btnDownTexture;//換上壓下的texture _msgText.text = target.name + " began!";//顯示訊息 return; } touch = e.getTouch(this, TouchPhase.ENDED);//針對ENDED處理 if(touch) { target.texture = _btnTexture;//換上一般狀態的Texture if (touch.tapCount == 2)//使用touch.tapCount可知道短時間內點了幾次 { _msgText.text = target.name + " double click(tab)!";//連點兩次為double click(tab) }else { _msgText.text = target.name + " end!";//單點的訊息 } return; } touch = e.getTouch(this, TouchPhase.MOVED);//針對MOVE處理 if(touch) { target.texture = _btnHoverTexture;//換上Hover的Texture _msgText.text = target.name + " move!";//顯示訊息 return; } touch = e.getTouch(this, TouchPhase.HOVER);//針對HOVER處理 if(touch) { target.texture = _btnHoverTexture;//換上Hover的Texture _msgText.text = target.name + " hover!";//顯示訊息 return; } touch = e.getTouch(this);//偵測Mouse Out的方法,有事件發生但抓不到Touch,代表Mouse Out if (touch == null) target.texture = _btnTexture; _msgText.text = target.name + " out!"; return; } } }
以上的程式碼應該很直覺,註解也都附上了。主要是使用e.getTouch()的第二個參數限定我們取到的TouchPhase,然後去做相對應的處理。第一個則是一個DisplayObject,說是要設定touch座標系參考的物件用的,不過Touch裡並沒有local座標的資訊,所以我看不出丟不一樣的DisplayObject有甚麼差別。touch.tapCount可以計算出這個Touch短時間內tap了幾次,所以可以用來做double click等效果。最後是Mouse Out,參考了Starling作者在論壇的回覆,當滑鼠離開DisplayObject時會發出一次TouchEvent,但不帶Touch。根據這個詭異的規則,我們就可以偵測當touch == null時就是Mouse Out。實際測試發現,當滑鼠離開一個物件確實會觸發這個狀態,但若滑鼠又很快進入其他物件的話,則可能不會有這個狀態。所以只能等看看作者會不會去修復這個問題了。Demo如下:
點我或圖看Demo
上一篇:一起來玩鳥 Starling Framework(3)Button!
下一篇:一起來玩鳥 Starling Framework(5)Multi-Touch
stage好像沒辦法偵聽到TouchEvent耶~
回覆刪除不好意思,如果要在starling做針對stage偵聽像native的MouseEvent.MOUSE_MOVE的話可以怎麼做呀?
To EricKuo:
回覆刪除也許你要在場景上墊個bg,有實際的內容才會觸發TouchEvent,我通常是對Sprite監聽TouchEvent,然後看看TouchPhase.HOVER是不是符合你的需要
再不然....EnterFrameEvent自己去監控Mouse座標囉,另外也可以上Starling論壇找找MouseEvent的extension,我記得有人寫出滾輪的事件,MouseMove不知道有沒有
Gray 謝謝你的回答唷~
刪除我最後一樣用stage偵聽,不同的是我用getTouch時第一個參數我帶stage,就可以聽得到了~
不過我還是不太懂第一個參數是什麼意思!? : )