воскресенье, 30 августа 2009 г.

ActionScript Mouse Events and Delegation

If you’ve used Flash MovieClips events onRollOver, onRollOut, onRelease,onReleaseOutside or onPress you’ve probably encountered the annoying little Flash shortcoming, that you can’t define mouse event-handlers on MovieClips contained inside MovieClips that have a mouse event defined.

Suppose you have something like this:

this.onRelease = doSomething;
this.createEmptyMovieClip(”childMC”,this.getNextHighestDepth());
var childMC:MovieClip = this["childMC"];
//Add some code to put something inside childMC
childMC.onRollOver = doSomethingElse;

The code in the function doSomethingElse will never be reached, because all mouse events are “caught” by childMC’s parent MovieClip.

A workaround that I use is to check in the parent functions whether the events apply to children.

Here’s an example for the onRelease event:

this.onRelease = function()
{

if (childMC.hitTest(_root._xmouse, _root._ymouse, true)) {

doSomethingElse();

}

}

The MovieClip function hitTest is used to test whether the mouse is hovering above the childMC when released. hitTest takes as arguments the x and y coordinates of the mouse relative to the _root MovieClip and a boolean that specifies whether to do the hitTest using the actual MovieClip shape (true) or just it’s bounding box (false).

Delegation

Sometimes you may want to base the logic in a mouse handling event on data that’s stored in another MovieClip, of course you can expose the decisions variables by making them public variables and accessing them through some relative path like _parent.var1 or this.childMC.var1 but a cleaner solution might be using Flash delegate creator available in Flash 8 professional. I learned how to use it throughthis Delegate tutorial. With delegates you can define mouse event handlers that execute in a object scope other then the MovieClip object scope on which they are defined! This how I used it for example. I had a ‘parent’ MovieClip showing a JPG image. In the MovieClip was ‘child’ MovieClip called zoomer, that when pressed should open a new browser window containing a high-res version of the JPG. Isensed that it would be better program design to have the knowledge about the image low-res and high-res version in the ‘parent’ MovieClip. Without use of a Delegate I should have either copied the knowledge of the high-res JPG to the child MovieClip or exposed that knowledge through the parents public interface. In my humble opinion the delegate approach is the cleanest, really leaving all the data and logic concerning JPG’s in the parent MovieClip.

Here’s how I used the delegate functionality:

import mx.utils.Delegate;
zoomer.onRelease = zoomer.onReleaseOutside = Delegate.create(this, handleOnRelease);

Комментариев нет: