The right way to do RollOver Event in AS3

I have been asking myself this question for a long time now. I see two ways of doing a roll over using ActionScript 3. The first one is pretty straight forward and it is the one you’ve seen everywhere. Here is some sampleĀ AS3 showing how to do it:

button.addEventListener(MouseEvent.ROLL_OVER, manageMouseOver, false, 0, true);
button.addEventListener(MouseEvent.ROLL_OUT, manageMouseOut, false, 0, true);
 
function manageMouseOver(event:MouseEvent):void{
  //your over code here
}
 
function manageMouseOut(event:MouseEvent):void{
  //your out code here
}

This is the classical way off doing thing. Doing it this way implies that for all your button you always have 2 listeners to do your rollovers. There is another way of doing this that will always use only one listener. Here it is

 
button.addEventListener(MouseEvent.ROLL_OVER, manageMouseOver, false, 0, true);
 
function manageMouseOver(event:MouseEvent):void{
  button.removeEventListener(MouseEvent.ROLL_OVER, manageMouseOver);
  button.addEventListener(MouseEvent.ROLL_OUT, manageMouseOut, false, 0, true);
  //your over code here
}
 
function manageMouseOut(event:MouseEvent):void{
  button.removeEventListener(MouseEvent.ROLL_OUT, manageMouseOver);
  button.addEventListener(MouseEvent.ROLL_OVER, manageMouseOut, false, 0, true);
  //your out code here
}

Doing it it this way, there will be less listener active at the same time, but each rollover will do 4 more actions. So is having less listeners worth doing more computations; is there situations where you should use one technique more than the other; or it has so little impact that we should not care about it?

I’d really like to know.

Following the indication in the comments I investigated the difference between MOUSE_OVER and ROLL_OVER and found that most of the time it is better to use ROLL_OVER.

Edits May 5th 2010
Because this post is now receiving a lot of traffic and it is one that I wrote so long ago, I felt obliged to update it a little. First off I would like to say that I would stick with method number 1 because it is just way easier to understand the code and method number 2 doesn’t save much (it just makes things more complicated, keep it simple). Secondly, I did some edits to the code itself; I removed the bad habits I used to have. I switched the MOUSE_OVER for ROLL_OVER because 99% of the time that is what you will need. I also change “e:MouseEvent” to “event:MouseEvent” as it is easier to read and it is the best practice that Adobe is pushing. Finally, I added “false, 0, true” at the end of my listener functions to set weakReference to true. In short, this is a fail safe if you forget to remove your listeners when you don’t need your button anymore. The button won’t be held into memory by the listeners. I just thought you should know.

,

  1. #1 by Case - April 29th, 2008 at 01:42

    Yeah! I’d like to know too!… maybe adding and removing listeners could itself be less efficient than setting them and leaving them alone??? Someone should do some tests…

  2. #2 by Haydn - May 27th, 2008 at 22:25

    It would probably be better to use MouseEvent.ROLL_OVER and MouseEvent.ROLL_OUT instead of MouseEvent.MOUSE_OVER and MouseEvent.MOUSE_OUT. That way if your button has nested display objects the event is only fired when the mouse enters or leaves the button, not for every single one of it’s descendants.

  3. #3 by dgelineau - May 29th, 2008 at 11:34

    Well, you could set mouseChildren = false and it would have the same behavior as ROLL_OVER. I am currently investigating the difference between ROLL_OVER and MOUSE_OVER.

  4. #4 by Dubai Web Design, Development - June 12th, 2008 at 23:23

    can we add background on mouse over or any effect like shades in css. Does any one have idea of that.

  5. #5 by holyhttp - May 3rd, 2009 at 13:20

    I think the first method is cleaner and more efficient. The event listener are set once the program is loaded. So no extra computation is needed afterwards.

    We have to keep in mind that events are fired at anytime you mouse the mouse over or out of an object in your flash movie. If not handler is found then the event bubbles up to the to of the object hierarchy.

    In the second case, not only you have the a similar event handling as the first example (//your over code here) but there is additional processing for constantly adding and removing an event listener.

    Even when using the second approach, you already have at least one event listener from the get go. You end up registering all those event handlers anyway.

    I really don’t think this second approach is elegant or efficient at all: just more coding.

    Would love to hear someone tell me othewise.

  6. #6 by Chris - May 7th, 2009 at 08:07

    I use a slightly different method:

    button.addEventListener(MouseEvent.MOUSE_OVER, button_events);
    button.addEventListener(MouseEvent.MOUSE_OUT, button_events);

    function button_events(e:MouseEvent):void {
    switch (e.type) {
    case “mouseOver”:
    // perform mouse over code
    break;

    case “mouseOut”:
    // perform mouse out code
    break;
    }
    }

    So, one listener function per interactive display object which acts as a ‘traffic cop’ for all incoming events. I seem to like doing things this way but wondered what you guys thought?

    C

  7. #7 by Zurie - July 14th, 2009 at 12:03

    function myNav($e:MouseEvent):void {
    var myObj:MovieClip = $e.currentTarget as MovieClip;
    // trace($e.type + ” : ” +$e.currentTarget.name ) ;
    if ($e.type == “mouseOver”) {
    trace(“over”);
    TweenMax.to(myObj, .6, {alpha:.3, ease:Sine.easeOut});
    }
    if ($e.type == “mouseDown”) {
    trace($e.currentTarget.name);
    if ($e.currentTarget.name == “navLeft_mc”) {
    Gaia.api.goto(“index/nav/solutions/insurance”);
    }
    if ($e.currentTarget.name == “navRight_mc”) {
    Gaia.api.goto(“index/nav/solutions/insurance”);
    }
    }
    if ($e.type ==”mouseOut”) {
    TweenMax.to(myObj, .6, {alpha:0, ease:Sine.easeOut});

    }
    }

  8. #8 by zedia.net - July 14th, 2009 at 16:10

    @Zurie
    I don’t know why but I don’t like to have all my mouse listener go to the same function. I prefer to have my function separate (one for rollOver, one for rollOut, etc). It is only esthetic I guess.

  9. #9 by Person - July 30th, 2009 at 20:00

    on actionscript 2 all you needed was

    on(rollover){
    insert your code
    }

    *sigh*

  10. #10 by mecrosis - September 4th, 2009 at 00:37

    actionscript 2 is fo suhkahs

  11. #11 by joel - November 5th, 2009 at 02:45

    hey I am trying to rollover over a button to play an animation. should be easy right? thanks

  12. #12 by joel - November 5th, 2009 at 15:38

    this sheds some light on the topic
    from :
    http://www.kirupa.com/forum/showthread.php?p=1948052

    rollOver and rollOut vs. mouseOver and mouseOut
    The InteractiveObject class (flash.display.InteractiveObject) in ActionScript 3 has both rollOver and rollOut events as well as mouseOver and mouseOut events.

    Both sets of events determine when a mouse enters or leaves the graphics area of an interactive object. The rollOver and mouseOver events fire when the mouse comes in contact with an interactive object, while rollOut and mouseOut occur when the mouse leaves the interactive object.

    Where they differ is with their interaction with interactive object children. The roll events (rollOver and rollOut) simplify the process and prevent interference with child events. Essentially, this is the same as using mouseOver and mouseOut with mouseEnabled set to false. mouseOver and mouseOut with mouseEnabled provide a parent sprite with events from its children. rollOver and rollOut keeps the events on the parent object.

    Example: toggle between the use of the ROLL_OVER & ROLL_OUT and MOUSE_OVER and MOUSE_OUT events.
    ActionScript Code:

    // main button
    var spriteButton:Sprite = new Sprite();
    spriteButton.name = “spriteButton”;

    // graphics
    var spriteGraphics1:Sprite = createGraphics(“spriteGraphics1″, 0xFF, 50, 50, 25);
    var spriteGraphics2:Sprite = createGraphics(“spriteGraphics2″, 0×80, 50, 50, 15);

    // add to display list
    spriteButton.addChild(spriteGraphics1);
    spriteButton.addChild(spriteGraphics2);
    addChild(spriteButton);

    // events
    spriteButton.addEventListener(MouseEvent.ROLL_OVER, over);
    spriteButton.addEventListener(MouseEvent.ROLL_OUT, out);
    //~spriteButton.addEventListener(MouseEvent.MOUSE_OVER, over);
    //~spriteButton.addEventListener(MouseEvent.MOUSE_OUT, out);

    function over(evt:MouseEvent):void {
    trace(“over: ” + evt.target.name);
    }
    function out(evt:MouseEvent):void {
    trace(“out: ” + evt.target.name);
    }

    // create circles
    function createGraphics(name:String, color:uint, x:Number, y:Number, radius:Number):Sprite {
    var circle:Sprite = new Sprite();
    circle.name = name;
    circle.graphics.beginFill(color);
    circle.graphics.drawCircle(x, y, radius);
    return circle;
    }

    You’ll notice that with rollOver and rollOut, spriteButton is the target and doesn’t receieve events from its children while the opposite is true for mouseOver and mouseOut.

    rollOver and rollOut output
    Code:

    over: spriteButton
    out: spriteButton
    over: spriteButton
    out: spriteButton

    mouseOver and mouseOut output
    Code:

    over: spriteGraphics1
    out: spriteGraphics1
    over: spriteGraphics2
    out: spriteGraphics2
    over: spriteGraphics1
    out: spriteGraphics1

  13. #13 by Almog Koren - November 24th, 2009 at 21:57

    This might help everyone
    ActionScript 3 Event Listeners Tips & Tricks
    http://www.almogdesign.net/blog/actionscript-3-event-listeners-tips-tricks/

  14. #14 by bish - January 16th, 2010 at 14:53

    Getting this error too:
    1026: Constructor functions must be instance methods.

  15. #15 by Edwinistrator - February 1st, 2010 at 19:32

    @Chris

    function myNav($e:MouseEvent):void {
    var myObj:MovieClip = $e.currentTarget as MovieClip;
    //etcetera…
    }

    How should I use this code or call this function?
    This is exact what I try to do, a general function to add the same functionality to multiple buttons.

  16. #16 by Edwinistrator - February 2nd, 2010 at 08:57

    this is my solution of multiple buttons on a stage. Give them class name ClickableMovieClip

    and put this code in ClickableMovieClip.as

    package {
    import flash.display.MovieClip;
    import flash.events.*;
    import com.greensock.*;
    import com.greensock.easing.*;
    class ClickableMovieClip extends MovieClip {
    function ClickableMovieClip():void {
    this.buttonMode = true;
    this.useHandCursor = true;
    this.addEventListener(MouseEvent.ROLL_OVER, onRollOverHandler);
    this.addEventListener(MouseEvent.CLICK, onClickHandler);
    this.addEventListener(MouseEvent.ROLL_OUT, onRollOutHandler);
    }
    function onRollOverHandler(myEvent:MouseEvent) {
    trace(“rollover”);
    //TweenMax.to(this, 1, {x:65, y:117});
    TweenMax.to(this, 0.3, {glowFilter:{color:0xff0000, alpha:1, blurX:16, blurY:16, strength:0.5}});
    }
    function onClickHandler(myEvent:MouseEvent) {
    trace(“click, naam: “+this.name);
    }
    function onRollOutHandler(myEvent:MouseEvent) {
    trace(“rollout”);
    TweenMax.to(this, 0.3, {glowFilter:{color:0xff0000, alpha:0, blurX:0, blurY:0, strength:0.5}});
    }
    }
    }

  17. #17 by sinozzuke - March 18th, 2010 at 10:07

    @Edwinistrator
    Hi!. I’m trying to use your metod, but I have done a ClickableMovieClip.as and import this to my file. But don’t know how to use it. This way?:

    var botonsector:ClickableMovieClip = new btn();

  18. #18 by Madelon - June 20th, 2010 at 07:31

    Great Help!! Thanks :D

  19. #19 by Christian - June 22nd, 2010 at 13:59

    Yes, you’ve eliminated one of the roll over listeners, but you still need a click listener…. after all it is a button…

  20. #20 by Giorgos - July 26th, 2010 at 06:49

    I agree with you post.

    However let’s not go crazy with naming conventions. There is a limit on what we should do.
    I am very strict on commenting, naming variables and function and all other “best practises”. I agree with 99% of them.
    But to actually have to name the event in the listener signature event instead of e it’s totally nuts.
    Let’s not assume that everybode else is stupid!!
    And it’s not the same like naming variables! A variable has to have a descriptive name as it can be anything (and be anywhere). In a listener’s signature, the first argument is always an event. So what’s the point on naming it event? Waste of 4 characters!!! ;)

    thanks

    Giorgos

  21. #21 by RazorX - July 27th, 2010 at 11:19

    It seems better to use ROLL_OVER, but what makes things difficult (especially for beginners) is that in Flash CS5 Pro the code snippets feature pumps out MouseEvent.MOUSE_OVER and in the comments they don’t even tell you you need to be mindful of possibly needing to add in mouseChildren = false; to avoid nested movieclip blinking. :(

  22. #22 by Hozefa - August 3rd, 2010 at 02:43

    @Edwinistrator
    Hi Can you please upload the complete file in a zip format. It will be real helpful to me

  23. #23 by Dave Sharpe - September 13th, 2010 at 18:06

    I have been searching on buttons. I am not super proficient in AS3. I have having an issue with buttons. I have a master movie with navigation that loads a series of external swfs. The external swfs have buttons, which navigate their timeline. My issue, the cursor does not change to pointer on rollOver over the buttons in the external swfs are loaded. The pointer changes when these movies are played individually, but not when loaded through the main movie. It seems to be a bug. It does work sometimes, but not always. I have a lot of buttons, would hate to write an rollOver, rollOut for 200 buttons. Any ideas what what may be wrong?

  24. #24 by CAKE - August 17th, 2011 at 17:03

    Hey. Thank you for this fine piece of information. I like your approach on this one.

    Have cake.

    BUTTERFLY CAKE.

  25. #25 by Canbey Bilgili - January 2nd, 2012 at 10:57

    Thank you. I think you should update
    function manageMouseOut(event:MouseEvent):void{
    button.removeEventListener(MouseEvent.ROLL_OUT, manageMouseOver);
    button.addEventListener(MouseEvent.ROLL_OVER, manageMouseOut, false, 0, true);
    //your out code here
    }

    as

    function manageMouseOut(event:MouseEvent):void{
    button.removeEventListener(MouseEvent.ROLL_OVER, manageMouseOver);
    button.addEventListener(MouseEvent.ROLL_OUT, manageMouseOut, false, 0, true);
    //your out code here
    }

  26. #26 by Ghelle - April 1st, 2012 at 06:47

    I corrected the manageMouseOver function and added multiple listeners to menu buttons.

    for(var i=1; i<8; i++){
    MMenu["b"+String(i)].alpha = 0;
    MMenu["b"+String(i)].buttonMode = true;
    MMenu["b"+String(i)].addEventListener(MouseEvent.ROLL_OVER, manageMouseOver, false, 0, true);
    };

    function manageMouseOver(event:MouseEvent):void{
    trace(event.target.name)
    var tar = event.target;
    tar.removeEventListener(MouseEvent.ROLL_OVER, manageMouseOver);
    tar.addEventListener(MouseEvent.ROLL_OUT, manageMouseOut, false, 0, true);
    tar.alpha = 1;
    }

    function manageMouseOut(event:MouseEvent):void{
    var tar = event.target;
    tar.removeEventListener(MouseEvent.ROLL_OUT, manageMouseOut);
    tar.addEventListener(MouseEvent.ROLL_OVER, manageMouseOver, false, 0, true);
    tar.alpha = 0;
    }

    Chris your method looks good too.

  27. #27 by Kelly - May 23rd, 2012 at 10:16

    I’m working on a map and I need each country to change color and display the name of the country and the city the my client is in on Rollover. I can get one country to work using the following script:
    thailandButton.addEventListener(MouseEvent.ROLL_OVER, btnOver);
    thailandButton.addEventListener(MouseEvent.ROLL_OUT, btnOut);

    function btnOver(event:MouseEvent):void {
    thailandButton.gotoAndPlay(“Over”);

    }
    function btnOut(event:MouseEvent):void {
    thailandButton.gotoAndPlay(“Out”);
    }

    However, when I try to use the same script and replace the name for each country, all of the countries start flashing to the same time and I can’t rollover anything. Can anyone help?

(will not be published)
Subscribe to comments feed