Thursday, January 22, 2009

Simple solution for MOUSE_WHEEL events on Mac

Flash does not support the MOUSE_WHEEL event for Macs. I was hoping it would be supported in version 9, and again in Flash 10 but I'm still waiting. There have been a number of solutions out there, and the best one I've found is Gabriel Bucknall's MacMouseWheel code. It consists of an actionscript class and some javascript code that will work together to have the browser pass the mouse wheel events to your Flash code.

After reading an awesome article by Peter McBride called JavaScript and VBScript Injection in ActionScript 3, I've put together a single as3 class that fixes the MOUSE_WHEEL problem without the need for any external javascript code. It works on Safari, FireFox and Opera and probably Chrome when it becomes available on the Mac.

The trick was to inject the mouse handling javascript code using ExternalInterface. The code finds the DOM node for itself, intercepts and passes the mouse wheel events which are then disributed to the current InteractiveObject under the cursor.

An example of initialization would be:

class awesomeapp extends Sprite {
public function awesomeapp() {
addEventListener(Event.ADDED_TO_STAGE, stage_init);
}
private function stage_init(e:Event):void {
MacMouseWheelHandler.init(stage);
addEventListener(MouseEvent.MOUSE_WHEEL, wheel_event);
}
}

Download the source (MIT license).

25 comments:

Kim said...

Cool stuff...I'm trying it out.
I just added a ":void" to the function in line 60 since FlexBuilder was bitchin' about your function not having a return value.

Good job man!

JesterXL said...

Dude, frikin' lifesaver, really easy to use, and works out of the box in my Flex project. Thanks a ton for sharing this!

Anonymous said...

Be sure to drop a vote for the bug itself in the Adobe bug tracker:

http://bugs.adobe.com/jira/browse/FP-503

Anonymous said...

This is terrific, but could you write a short example how to use it…i cant get it by my self…this would be nice :c)

zh. said...

Nice class, but it disables page scrolling in browser at all. Not only when mouse is over flash.
I tried to fix it, but no luck.

ed said...

Hi,
I tweaked this code to also allow the wheel to work on pc when wmode is being used in the *object* or *embed* tag.

code is here:
http://code.google.com/p/flex-wmode-mousewheel-handler-example/

Penguin said...

Hi, I am a novice Flash developer. Can someone please explains to me in basic steps (1,2,3) how to make this work on a Mac? Where do I put the MacMouseWheelHandler.as file

I am using this actionsctipt to scroll through my timeline


function scrollTime (event:MouseEvent):void
{
if (event.delta < 0)
{
nextFrame();
timeFrame ++;
trace (timeFrame);
scrollAxial_mc.value = timeFrame;
}
else
{
prevFrame();

timeFrame --;
scrollAxial_mc.value = timeFrame;
if (timeFrame <1 )
{
timeFrame = 1;
}
}
}


Many thanks to whoever answers this question. Help me please.

Pedro said...

Hello,
I´ve noticed that in safari the scrollbars of the browser stopped working is there a solution so that we can switch on/off the flash mousewheel support?

Thanks in advance

groupe de discussion said...

Super çà marche parfaitement pour moi, preuve à l'appuie :

http://www.centre-culturel-de-la-sar de la sarthe.com
allz dans une des rubriques où il y a un scroll !

Great it works for me !
the evidences on http://www.centre-culturel-de-la-sarthe.com

Thank you !

PEZ said...

Lovely!

Robert said...

Crazy easy to implement and works great!

<mx:Application ... creationComplete="init()"

<mx:Script>

import com.earthbrowser.MacMouseWheelHandler;

public function init():void{
      this.addEventListener(Event.ADDED_TO_STAGE, stage_init);

public function stage_init(e:Event):void {
    
MacMouseWheelHandler.init(stage);
}

</mx:Script>
.
.
.

Patrick said...

Hi there,
Can someone post an example? I tried inserting the code into the timeline as well as referencing it via the Document class.

Thank you!

Anonymous said...

ridiculous simply to implement!
Thanks a lot for this one!

For timeline-coders:
put the com folder in the right place and import the class using:

import com.earthbrowser.ebutils.MacMouseWheelHandler;


MacMouseWheelHandler.init(stage)

and there you go

tomek said...

Awesome! Thank you...

tomek

Rob said...

Just out of curiosity, is there any particular reason eb.findSwf iterates through the objects and embeds like it does rather than just using document.getElementById?

Rob said...

I just reread the code and figured out why, though it still seems like there should be a better way to do this.

Anonymous said...

this is by far the best solution on this matter (adobe should fix this) Thank you so much

NotarySojac said...

This is very interesting - the functionality is there if the app is being DEBUGGED from within the Flash IDE - but NOT THERE if just running 'TEST PROJECT' and NOT THERE when I run the app up in an HTML page.

Can anyone suggest what it is I am missing that will not let the MOUSE_WHEEL events be seen when NOT in the Flash DEBUG mode?

Anonymous said...

Hi it works fine for me here :
http://www.vetements-bambous.fr/boutique/index.php?option=com_virtuemart&Itemid=64&lang=fr&var_flexmode=1

but it dosent works on IE (7-8)

Does anybody make it works with IE ?

David Coletta said...

I found that with Safari 4.0.5, there were some problems with the direction of the scroll wheel events. It appeared as if the events were in the same direction no matter whether the wheel was scrolled up or down.

Fixed by adding the following line of code just before calling swf.ExternalMouseEvent():

if (eb.browser.safari && delta > 0.0)
delta += 1.0;

heiko said...

Thanks for sharing this - works a treat in Firefox and Chrome. However I am experiencing issues in Safari 4.05 - scrolling works but then jumps back in same direction. I tried David's fix, but it's not working for me. Would appreciate your feedback on this.

heiko said...

Check my site in Safari 4.0.5 and try using mousewheel over thumbnails. It works but immediately snaps back to start position.

heiko said...

I worked it out! Safari 4.0.5 works perfectly fine now. The weird thing is that it always worked in fullscreen mode.

if(eb.browser.safari) {
if(delta > 0){
delta += 1;
}
if(delta < 0){
delta -= 1;
}
}
swf.externalMouseEvent(delta);

titouille said...

Work perfect with the heiko add. Thanks a lot for sharing

Majakovskij said...

Thanks a TON!