Mac OS X Mouse Wheel Support for ActionScript 3 Flash Applications (v.2+)

Posted on April 26, 2008
Filed under ActionScript 3, Flex, Mac, Programming

AS3 Mouse Wheel support picture So I’ve finally updated the solution I’ve made earlier for enabling Mac OS X mouse wheel support in Flex applications to a second version. I didn’t want to continue adding stuff into the original post, so I decided to write a separate post just for this new version. As you can see from the title, this version should work in any Flash project you’re writing in ActionScript 3, as opposed to just in Flex projects. This change was contributed by Pavel Fljot, and all the other stuff I’ve added since have been added on top of that. Deployment should now be a lot easier and some features that were missing in the first version have also been added.

Changelog

First, here is an itemized list of what has changed:

Determining the InteractiveObject to dispatch the mouse wheel event

Like mentioned in the changelog above, I’ve added an another method for finding the InteractiveObject on stage and under the mouse cursor that should dispatch the mouse wheel event when one is sent from the JavaScript end. This is based on the solution to this same issue Gabriel Bucknall has come up with at pixelbreaker.com. My solution basically went through the whole display list hierarcy every time a mouse wheel event had to be dispatched, trying to find mouse-enabled InteractiveObjects that were under the mouse cursor, and then asked the topmost of these to dispatch the MouseEvent. Gabriel’s solution was to attach a MouseEvent.MOUSE_MOVE event listener to the Stage and keep a reference to the object that was the target for the last such event, and then use that reference to ask this object to dispatch the mouse wheel event whenever required.

Now, the main difference between these two solutions, I’ve found, is that Gabriel’s is faster but inaccurate in some border cases, while mine is slower but more accurate. The slowness of my solution is very clear if you understand the amount of processing that goes on whenever the user starts rolling the wheel: for each event, the application needs to go through the whole hierarchy of objects on the Stage, find InteractiveObjects that are under the mouse cursor, mouse-enabled and visible, and then find the one of those that is deepest in the display list. Gabriel’s solution doesn’t need to do any of this: it already has the InteractiveObject reference it wants to use at this point. The inaccuracy, on the other hand, stems from the fact that if the user doesn’t move their mouse, the reference won’t get updated. What this means is that if the InteractiveObjects on Stage have moved (in relation to the mouse cursor,) or been added to or removed from the display list while the cursor has stayed put, the reference will not be up to date, and probably incorrect.

As you’ve probably deduced from the last paragraph, there are upsides and downsides to both of these approaches, and I at least would like to be able to choose which one to use, based on the context of what I happen to be doing at the moment. This is why I’ve added this exact feature into the code in the form of a property the value of which you can set at will:

private var _mwSupport:ExternalMouseWheelSupport = ExternalMouseWheelSupport.getInstance(stage);

_mwSupport.dispatchingObjectDeterminationMethod = ExternalMouseWheelSupport.COPY_MOUSEMOVE_EVENTS;
// or
_mwSupport.dispatchingObjectDeterminationMethod = ExternalMouseWheelSupport.TRAVERSE_DISPLAY_LIST;

You can test the differences between these two options with the demo.

Deployment and use

So like I wrote before, the process of deploying and initializing this solution has changed a bit from the last version. This is how you do it now.

  1. Include the JavaScript file onto the page that embeds the Flash object(s)
  2. <script type="text/javascript" src="./extMouseWheel.js"></script>

  3. Make sure your embedded Flash objects have a parent div element
  4. <div style="width:600px;height:600px;" id="flashContainerDiv">
      <!-- add Flash object's <object> and <embed> tags here -->
    </div>

  5. In your AS3 code, get a reference to the singleton instance of ExternalMouseWheelSupport in at least one place
  6. As you can see, the singleton instance accessor is not a property anymore, but a method, so that you can pass a reference to the Stage to it. This change is because of the removal of dependencies to Flex libraries, which could be used to access the Stage instance in the previous version.

    import org.hasseg.externalMouseWheel.ExternalMouseWheelSupport;
    private var _mwSupport:ExternalMouseWheelSupport = ExternalMouseWheelSupport.getInstance(stage);
    

    I generally do this in the applicationComplete event handler, but you can of course call it wherever you want, as long as you make sure the Stage reference you’re using is not null (an Error will be thrown if it is.)

…and that’s it. :)

Downloads and demo

This code is licensed under the MIT License.

Other info

I’ve tested this solution with the following browsers (sadly, Opera on the Mac isn’t supported since ExternalInterface doesn’t seem to work in the latest version:)

If someone could please test this on the Mac OS version of Firefox 2 and the Windows versions of Firefox 3 beta and IE 6, I’d very much appreciate it.

Comments

75 Responses to “Mac OS X Mouse Wheel Support for ActionScript 3 Flash Applications (v.2+)”

Show/hide comments & reply form: