ActionScript 3.0 GestureEvent: Working with Gestures on Mobile
When working with high level and complex structures like Design Patterns, the focus is squarely on the relationship between objects—classes, inheritance, composition, implementation, interfaces and related concepts and structures. The “details” are the details of these various relationships and how they work in concert. Using Algorithm 1 or Algorithm 2 is only pertinent insofar as it relates to a method or property that needs to be loosely bound to some other object. If you start thinking about algorithm details as a primary concern and fretting over internals, you can easily lose sight of the larger structures that are under development and never really understand Design Patterns.
Seismic Shift
Every now and again we encounter a seismic shift in the way things are done, and you have to make adjustments.(Some of you may remember the Commodore 64 that went the way of the Dodo Bird. At one time it was the most popular personal computer on earth, but if you insisted on sticking with it, you probably don’t have any clients for your services.) In my own case, shift to mobile devices forced me to spend some quality time with the event processes in ActionScript 3.0. Going to the base, I reviewed how the Display List is handled in Flash and by AS3. Then I went to look at the AS3 Event Flow and among the several articles I read, one of the best is Jody Hall’s. Adobe has several good ones as well, and I’m sure many more are available that some of you may want to share.
On to Gestures
I wrote some gesture events and handlers. The results were unsatisfactory. It wasn’t that they didn’t work, but after one would work, another would not. Very baffling and frustrating. My goal was to create a ‘workbench’ where I could try all kinds of gesture events, but I had very poor luck with just about everything at some point. So I backed away and tried an application with only two gestures; neither available with MouseEvent. One was Rotate and the other Zoom. Christian Cantrell has a good article on using gestures, and in addition to getting some good information on using gesture events, I also got a nice little piece on using gestures with bitmaps. (I had been having a devil of a time with Sprite objects in the Library with gestures.) Click the download button below to get the source code and FLA files for Flash Pro 5.5, 5 and 4 along with the image files and ActionScript 3.0 code:
In my last post, I was convinced that TOUCH_TAP from TouchEvent works better than CLICK from MouseEvent with a mobile device. That conclusion was not based on the inner-workings of events and event handling, but rather from testing the different event handlers using my iOS device, a 4S iPhone. In the Adobe documentation, they point out that it might be better to use a MouseEvent rather than a TouchEvent or GestureEvent. It depends on the app, device and device OS. That pretty much makes it an empirical question.
In this application, there was no choice to use MouseEvent because it does not contain the required finger-flipping gestures I can make on my iPhone—GESTURE_ZOOM and GESTURE_ROTATE. Likewise, TouchEvent did not have the kinds of gestures; so I had to use TransformGestureEvent. The following code shows how it is employed in a simple picture flipping/zooming app:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | package { import flash.display.Bitmap; import flash.display.Sprite; import flash.events.TransformGestureEvent; import flash.ui.Multitouch; import flash.ui.MultitouchInputMode; [SWF(width=640, height=960, frameRate=24, backgroundColor=0xcc0000)] public class PicFlip extends Sprite { [Embed(source = "vanBillz.png")] public static var BillzImage:Class; private static var billzBitmap:Bitmap = new BillzImage(); private static var carrier:Sprite = new Sprite(); public function PicFlip() { carrier.x = 320, carrier.y = 550; carrier.addChild(billzBitmap); billzBitmap.x = (320 - (billzBitmap.bitmapData.width / 2)) * -1; billzBitmap.y = (480 - (billzBitmap.bitmapData.height / 2)) *-1; this.addChild(carrier); Multitouch.inputMode = MultitouchInputMode.GESTURE; carrier.addEventListener(TransformGestureEvent.GESTURE_ZOOM, doZoom); carrier.addEventListener(TransformGestureEvent.GESTURE_ROTATE, doRotate); } private final function doZoom(e:TransformGestureEvent):void { carrier = e.target as Sprite; carrier.scaleX *= e.scaleX; carrier.scaleY *= e.scaleY; } private final function doRotate(e:TransformGestureEvent):void { carrier = e.target as Sprite; carrier.rotation += e.rotation; } } } |
I tested it on an iPhone, but there’s no reason it won’t work perfectly well on an Android or some other mobile device. Further, I found it to be very responsive. The zooming seemed to work quite well with bitmapped graphics, and so I assumed that it would work just as well, if not better with a vector object in the Library. So I put together a little test symbol using the drawing tools in Flash and stored it as Sprite class in the Library. (By the way, in case you were not aware, to make a Sprite class in the Library, when you create a New Symbol, just classify it as a MovieClip and in the Base Class window change the type from flash.display.MovieClip -> flash.display.Sprite. The Library icon turns from Blue to Green to indicate it is now a Sprite.)
I used the following code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | package { import flash.display.Sprite; import flash.events.TransformGestureEvent; import flash.ui.Multitouch; import flash.ui.MultitouchInputMode; public class PicFlipLib extends Sprite { private static var carrier:Sprite = new Sprite(); private static var billzVector:Sprite=new BillzVector(); public function PicFlipLib() { carrier.x = 220, carrier.y = 350; carrier.addChild(billzVector); this.addChild(carrier); Multitouch.inputMode = MultitouchInputMode.GESTURE; carrier.addEventListener(TransformGestureEvent.GESTURE_ZOOM, doZoom); carrier.addEventListener(TransformGestureEvent.GESTURE_ROTATE, doRotate); } private final function doZoom(e:TransformGestureEvent):void { carrier = e.target as Sprite; carrier.scaleX *= e.scaleX; carrier.scaleY *= e.scaleY; } private final function doRotate(e:TransformGestureEvent):void { carrier = e.target as Sprite; carrier.rotation += e.rotation; } } } |
One of the features that seemed to make a difference was that instead of having the event listener connected directly to the Library Sprite (BillzVector), I used an object container Sprite, carrier. Figure 1 shows the zoom and rotation on an iPhone 4S. This was used with both the bitmap and the vector Sprite objects, and they both worked quite well.
Back to Design Patterns
I was going to post my final matrix motion solution, but I got jammed up with event handling. Next time, I should be able to post the next stage in my Samurai game. It uses a State design pattern to move through nine cells in a 3 X 3 matrix. Everything was working well except that my event handlers were not as crisp as I wanted. I’ll have a chance to see now whether the time-out with AS3 event handlers was enough. The Design Pattern does its job; I just was not getting the event handlers to do theirs. In the next post you’ll be able to see whether they are all working well together in a mobile environment.



Bill Sanders
hi friend, and would do to limit the zoom?
Hi Julio,
Right off the top of my head, I’d add a zoom limit variable. The code would look something like this:
There might be a better way, but try that for now.
Kindest regards,
Bill
hello, and would do to always centered in the middle?