AS3 Mouse Events, No More Invisible Buttons

Here is a small tutorial on scripting and its great changes in AS3 from AS2/AS1 thinking, we are focusing on mouse events currently.

The great thing about Flash9 and specifically AS3 (Actionscript3) is that it is starting to become a real programming platform and losing many of the silly hacks that is used to have. This is a good thing.

Old hacks like tellTarget are finally gone. Pixel level manipulation is possible and even faster. Real frameworks, excellent structured animation kits and even 3d engines are being built everyday. And invisible buttons are not needed anymore!

Like when people migrated from desktop to web, or VB6 to .NET, or OO to functional, we tend to try to reimplement the same solutions in new platforms even if there are better options because it worked before.

How to make movieclip buttons without invisible buttons via AS3 script…

Anything can be clickable and a button in AS3. Link a class to an object in a movie, dynamicly drawn asset or external asset and you are ready to make it a button.

Take for instance:

package draw.logic.tests
{
 import flash.display.*;
 import flash.events.*;

 public class GamePlayButton extends MovieClip
 { 
  public function GamePlayButton ()
  {
   this.addEventListener(MouseEvent.CLICK, onMouseClickEvent);   
  } 
  function onMouseClickEvent(event:Event):void
  {
    trace("mouse clicked on me");
  }
 }
}

You will note the addition of the event to the movie clip which makes it clickable.

this.addEventListener(MouseEvent.CLICK, onMouseClickEvent);

This again makes the movieclip clickable by listenting for the MouseEvent.CLICK event. This sample class can be linked to a movieclip for instance from the FLA library by going to Library > Properties then linking the class which would be draw.logic.tests.GamePlayButton in the above sample.

Great so we have a button now, on the MouseEvent.CLICK we are going to go to trace a message. All done right? Nope if you will notice the button does not get the linkable hand.

Make the Button Show the Mouse Cursor Hand

Well in old skool AS we might just slap an invisible button on there or make it a button type. Better yet let’s just set the this.buttonMode = true; in code which makes it a clickable button, listens to the click event, and get the hand to notify the user that it is a clickable item.

Sample script for a ‘play’ button

package draw.logic.tests
{
 import flash.display.*;
 import flash.events.*;

 public class GamePlayButton extends MovieClip
 { 
  public function GamePlayButton ()
  {
   this.buttonMode = true;   
   this.addEventListener(MouseEvent.CLICK, onMouseClickEvent);   
  } 
  function onMouseClickEvent(event:Event):void
  {
    parent.gotoAndPlay("game");
  }
 }
}

Good Architecture and Design

In the past most items could be moved to .as files but you would have this mix of people that still put onEnterFrames or button click on(release) code in the FLA itself. AS3 I think finally makes it fully possible to remove code entirely from the FLA with only stop(); scripts for different frames.

A nice way to be is to have all script in external libraries and files removing all script from the FLA if possible. The script for buttons to the script for the main document class. The FLA is essentially just needed for library movieclips and AS3 real forces this separation. That combined with its general better structure makes this a much better platform than AS2 and Flash8, stop wasting your time developing in that and get to AS3 (take a gander at the better structured libraries in this migration link).

Best part of AS3 is the new clean event model, the basis on Javascript 2 spec and the clearer separation of code and assets for flash. More on the Mouse and Event model in AS3 and Timers, Loaders and more coming soon.

Advertisements

32 Responses to “AS3 Mouse Events, No More Invisible Buttons”

  1. Josh Says:

    “A nice way to be is to have all script in external libraries and files removing all script from the FLA if possible. The script for buttons to the script for the main document class. The FLA is essentially just needed for library movieclips and AS3 real forces this separation. That combined with its general better structure makes this a much better platform than AS2 and Flash8, stop wasting your time developing in that and get to AS3 (take a gander at the better structured libraries in this migration link).”

    Actually the separation is not to make programming easier. It makes programming more like programming languages like C++, and to make flash movies run faster but programming itself is a lot harder than AS2. It might be a good thing for hardcore programmers like yourself, but for some who are real tuned AS2 and are not programming experts, it is quite a pain to learn. They usually find it better to use onClipEvent(enterFrame) and on(release) for simple simple little things. Developing in Flash 8 is actually not wasting time for some people who do not need to make an intensive flash program, but just need some buttons to work. Those people can easily use on(press) instead of adding functions and listeners which take up more code. Adobe realizes this and that is why Flash CS3 still allows people to create AS2 files.

  2. drawk Says:

    Hey Josh,

    I agree but to compete they needed a faster engine the AVM2 that AS3 runs in and this separation helps to speed things up by typing. I agree they will always probably have the CS3 IDE but other IDEs like FlashDevelop, FlexBuilder etc will probably change your mind in scripting. The ease of coding externally to flash to get things done is much cleaner and auto complete supported with many great tools. The Flash IDE for coding is not good.

    AS3 is hard and it is a leap, but anytime there is a chance to get ahead or make your apps perform 6-10 times faster with AS3 over AS2 you will have an advantage and as a solution provider that is key to staying competitive.

  3. Tink Says:

    “Great so we have a button now, on the MouseEvent.CLICK we are going to go to trace a message. All done right? Nope if you will notice the button does not get the linkable hand.”

    Buttons shouldn’t show a hand cursor, only text links should show a hand cursor. Hand cursors have been incorrectly displayed on buttons throughout the history of Flash and in AS 3.0 it’s finally been connected.

    You can test this theory but mousing over any button inside any app you have, you should get a rollover but no hand cursor.

  4. drawk Says:

    Yes that is true Tink but I believe that the web may have changed that pattern. The web changed alot, even the ability to change context in the same app and treat apps or sites like tv channels almost. Before it was a very tedious close, open next etc. Buttons preceded links and it was obvious they were clickable, big borders, deathly grey. Then the web came and they were like, how do we let the user know the link is clickable? It might be underlined but so are others. So they made the hand. Some would say the blue link is needed, I say it is the and moreso. Have you ever seen a form that has an image button for a submit button without cursor:hand in css/html/xhtml? It is extremely annoying. On the web context or within a browser, all clickable things get the hand in my opinion.

  5. menes Says:

    Hey guys! I started flash on flash 5, .. I lost track of flash after flash 8, and now just making this button seems a bit farfetched.. I still can’t find where to put all that text…

  6. Darryl Says:

    I have accepted that even as a designer not a developer I ought to start from scratch and learn AS3 but there is no doubt that it seems much more involved to get what used to be simple navigation up and running…

    Following a very similar structure to your example here Drawk I got some help to create a ‘Button’ class that would do save me duplicating code for each of the buttons I made…the latest set back is that when I try lo link the class as you suggest to more than one of my movieclip buttons i get a warning requesting that I enter:

    ‘a unique class name not associated with any other symbols’!!?

    Does this mean I have to create a class for every button after all? … arrrgh.

    (still thanks for at least helping me work out how to even attempt linking the class to my symbols!)

  7. ryan Says:

    Hey Darryl,

    Also, look at inheriting from SimpleButton. This is an option for only a button behavior. It has some wiring for the over states and etc if you don’t want to do that manually. You can still put code in the main timeline (externaly with .as or internally) and attach the class that way or have a simplebutton and then create a class for each button that inherits that. It is a bit more complex but in the end more simple, once you have it down, and then start looking back at AS2 code compared to AS3 code later on over time. You will be happy you made the switch. AS3 is much more readable and of course performs better.

  8. Darryl Says:

    Thanks ryan. Suspect I’m going to default to putting the code into the first and just writing out the couple of functions for each button. sort of a halfway house cop out I suspect but then thats what we designers are meant to do. ;oP

  9. drawk Says:

    Yeh the most important thing about coding, make sure you understand what you are putting in. Do that the way that works best for you. I tell everyone this. It is important to make it readable, and live a long life if possible, sometimes you have to hack it, other times you are doing it in a simple way due to complexity or so there is a low bar for other coders and maybe non coders/designers just looking to get it done. Or maybe it si only a short project. It is all about the life of the project and if others are goign to work on it or if you are going to put it out in the public. For instance, a 3 month promo might not make sense developing any type of global class libraries, but you might progress them over time to a platform with each iteration. Or using existing tools that are proven they can make it easier for others to work on and yourself when you come back later.

    The problem is there is many many ways to do things in Flash. And now we have Flex paths and patterns emerging, then still the Flash CS3 AS3 ers, then the AS2ers that are holding steady. The flash developer world is getting into different paths. I think that the Flex and Flash side should also come a little closer together. Just within flash some people put all code in the fla still, some mix it, some use the document class, some mix flash and flex with bridges, bulk gets added. It really should be streamlined and some of this might make more sense.

  10. Darryl Says:

    Low bar is right dude! I will take your advice and be sure to keep things as meaningful as possible for as long as possible….

    …on a semi-related note have you any idea why the compiled size of an .swf would bump up 1k or so on simplifying my code with a reusable class (compared to earlier when I had six almost identical functions!) If anything I was sort of expecting file size to go down a little. Not that it matters when were talking about a k or so, but curious all the same given the theoretical ‘streamlining’ I’ve been doing?

  11. drawk Says:

    Hey Darryl,

    You will have to check the size report, or you could try save and compact and then make sure compress file is on in the publish settings. Save and compact only takes care of the fla but sometimes it magically kicks down the size of the swf. Usually though if yuou just run a size report you can easily see where the byte bulk is coming from.

    If it is just a as based compile and there is less code sometimes virtual machine serialization is a block box.

  12. drawk Says:

    black box not block box

  13. Milouni Says:

    Hi there. Can anyone please help me getting the script below to work in an external Actionscript 3.0 file? I’m new to this and I would really appreciate if someone could help. I can’t it to work in an .as file. Below script for the fla file I have so far and i know I am supposed to name the Document Class which is Masking Content(what I named my .as file) The fla file is called maskingContent.fla

    function onComplete(eEvent:Event):void{
    addChild(imageLoader);
    //addChild method of image loader
    //next move actual image from the the corner
    imageLoader.x = stage.stageWidth/2 -imageLoader.width/2;
    imageLoader.y =40;

    }

    mcButton0.addEventListener(MouseEvent.CLICK, setRaindropMask);
    mcButton1.addEventListener(MouseEvent.CLICK, setSnowflakeMask);
    mcButton2.addEventListener(MouseEvent.CLICK, setSunshineMask);

    function setRaindropMask(eEvent:MouseEvent):void{
    var mcRaindropMask:RaindropMask= new RaindropMask();
    setMask(mcRaindropMask);
    }

    function setMask(mcMask:MovieClip):void{
    mcMask.x = imageLoader.x + imageLoader.width/2
    //x position
    mcMask.y = imageLoader.y + imageLoader.height/2
    imageLoader.mask = mcMask;

    }

    function setSnowflakeMask(eEvent:MouseEvent):void{
    var mcSnowflakeMask:SnowflakeMask= new SnowflakeMask();
    setMask(mcSnowflakeMask);

    }

    function setSunshineMask(eEvent:MouseEvent):void{
    var mcSunshineMask:SunshineMask= new SunshineMask();
    setMask(mcSunshineMask);

    }
    imageLoader.addEventListener(MouseEvent.CLICK, clearMask);
    function clearMask(eEvent:MouseEvent):void{
    imageLoader.mask = null;
    }
    //mcMask.buttonMode = true;

    Thank you

  14. drawk Says:

    I guess I would need more info on the errors but from the snippet you have here make sure imageLoader is iniialized and also this needs to be wrapped in a package{} tage that doesn’t need a namespace if it is in the same folder as the FLA file. Also make sure the document class is ‘MaskingContent’ and the .as file is ‘MaskingContent.as” and the class is marked as “MaskingContent”.

    package
    {
    var imgLoader:Loader = new Loader();

    public class MaskingContent extends Sprite {

    function onComplete(eEvent:Event):void{
    addChild(imageLoader);
    //addChild method of image loader
    //next move actual image from the the corner
    imageLoader.x = stage.stageWidth/2 -imageLoader.width/2;
    imageLoader.y =40;

    }

    public function MaskingContent() {

    mcButton0.addEventListener(MouseEvent.CLICK, setRaindropMask);
    mcButton1.addEventListener(MouseEvent.CLICK, setSnowflakeMask);
    mcButton2.addEventListener(MouseEvent.CLICK, setSunshineMask);
    }

    function setRaindropMask(eEvent:MouseEvent):void{
    var mcRaindropMask:RaindropMask= new RaindropMask();
    setMask(mcRaindropMask);
    }

    function setMask(mcMask:MovieClip):void{
    mcMask.x = imageLoader.x + imageLoader.width/2
    //x position
    mcMask.y = imageLoader.y + imageLoader.height/2
    imageLoader.mask = mcMask;

    }

    function setSnowflakeMask(eEvent:MouseEvent):void{
    var mcSnowflakeMask:SnowflakeMask= new SnowflakeMask();
    setMask(mcSnowflakeMask);

    }

    function setSunshineMask(eEvent:MouseEvent):void{
    var mcSunshineMask:SunshineMask= new SunshineMask();
    setMask(mcSunshineMask);

    }
    imageLoader.addEventListener(MouseEvent.CLICK, clearMask);
    function clearMask(eEvent:MouseEvent):void{
    imageLoader.mask = null;
    }
    //mcMask.buttonMode = true;

    }
    }

    What you can do if you are new to document classes is make sure this is running in the fla file itself. If it is take it and essentially wrap the whole thing in a package and class and move the initialization scripts to the class constructor. I haven’t tested this just a quick look but if using document classes you need to make sure the whole content is a class that extends from at least Sprite.

  15. drawk Says:

    A bit reordered

    package
    {
    var imgLoader:Loader = new Loader();

    public class MaskingContent extends Sprite {

    public function MaskingContent() {

    mcButton0.addEventListener(MouseEvent.CLICK, setRaindropMask);
    mcButton1.addEventListener(MouseEvent.CLICK, setSnowflakeMask);
    mcButton2.addEventListener(MouseEvent.CLICK, setSunshineMask);
    }

    function onComplete(eEvent:Event):void{
    addChild(imageLoader);
    //addChild method of image loader
    //next move actual image from the the corner
    imageLoader.x = stage.stageWidth/2 -imageLoader.width/2;
    imageLoader.y =40;

    }

    function setRaindropMask(eEvent:MouseEvent):void{
    var mcRaindropMask:RaindropMask= new RaindropMask();
    setMask(mcRaindropMask);
    }

    function setMask(mcMask:MovieClip):void{
    mcMask.x = imageLoader.x + imageLoader.width/2
    //x position
    mcMask.y = imageLoader.y + imageLoader.height/2
    imageLoader.mask = mcMask;
    imageLoader.addEventListener(MouseEvent.CLICK, clearMask);

    }

    function setSnowflakeMask(eEvent:MouseEvent):void{
    var mcSnowflakeMask:SnowflakeMask= new SnowflakeMask();
    setMask(mcSnowflakeMask);

    }

    function setSunshineMask(eEvent:MouseEvent):void{
    var mcSunshineMask:SunshineMask= new SunshineMask();
    setMask(mcSunshineMask);

    }

    function clearMask(eEvent:MouseEvent):void{
    imageLoader.mask = null;
    }
    //mcMask.buttonMode = true;

    }
    }

  16. drawk Says:

    If using a document external class you do all your even writing from the constructor of the document class or from the constructor you call other methods that attach the events and listeners.

    Try this out, actually sry I said Sprite but Document classes need MovieClip extends.

    http://www.kirupa.com/forum/showthread.php?p=1950401

    What I tend to do it create AS3 libraries that can be used in FLash or FLex and usually do not use the document class as I have found it is hard to get creative teams or reusing in flex more difficult. So I create an api and then in a mini document class I call that api initialization or I just put the initialization in the frame of the FLA. Depends on who will be working on it later, programmers or creatives.

  17. graeme Says:

    hello
    i am new to AS3 and i was just wondering if anyone can help me.
    i have created a button in flash and put animation onto it, but i want to make the button a link to a website but have not been able to do so. if anyone can help that would be great

    graeme

    here is the actionscripting for the animation if it helps

    myBtn.buttonMode = true;
    myBtn.addEventListener(MouseEvent.ROLL_OVER,animIn);
    myBtn.addEventListener(MouseEvent.ROLL_OUT,animOut);
    function animIn(event:MouseEvent):void {
    myBtn.gotoAndPlay(5);
    }
    function animOut(event:MouseEvent):void{
    myBtn.gotoAndPlay(20);
    }

  18. ryan Says:

    Just add a mouse down event like you have the roll over and out and in the event handler method call the navigateToURL method.

  19. graeme Says:

    hello
    i have added a mouse down event like you said and the navigateToURL but when i click on the button it comes up that the navigateToURL isnt a function

    heres what i typed in

    myBtn.buttonMode = true;
    myBtn.addEventListener(MouseEvent.ROLL_OVER,animIn);
    myBtn.addEventListener(MouseEvent.ROLL_OUT,animOut);
    myBtn.addEventListener(MouseEvent.MOUSE_DOWN,home);
    function animIn(event:MouseEvent):void {
    myBtn.gotoAndPlay(5);
    }
    function animOut(event:MouseEvent):void{
    myBtn.gotoAndPlay(20);
    }
    function home(event:MouseEvent):void{
    myBtn.navigateToURL(“http://www.liv.ac.uk/”);
    }

  20. ryan Says:

    Be sure to include flash.net.* as that contains the method: http://livedocs.adobe.com/flex/2/langref/flash/net/package.html

    Also, no need for the myBtn.navigateToURL. It is a stand along function. You could attach it to your myBtn but plain is fine.

    Sample with request and necessary imports:

    package {
    import flash.display.Sprite;
    import flash.net.navigateToURL;
    import flash.net.URLRequest;
    import flash.net.URLVariables;

    public class NavigateToURLExample extends Sprite {

    public function NavigateToURLExample() {
    var url:String = “http://www.adobe.com”;
    var variables:URLVariables = new URLVariables();
    variables.exampleSessionId = new Date().getTime();
    variables.exampleUserLabel = “Your Name”;
    var request:URLRequest = new URLRequest(url);
    request.data = variables;
    try {
    navigateToURL(request);
    }
    catch (e:Error) {
    // handle error here
    }
    }
    }
    }

  21. Alethea Says:

    I know I am probably in the minority but I really do not like the changes in Flash, the main reason for this being that I teach ICT in a UK secondary school.

    With AS2 and it was easy enough to have even my year 7’s create simple games (missile command, Pacman) and banners for their coursework.

    Now even our year 10 top sets struggle and from next year we will be dropping this from the curriculum as the increased complexity of the code and time required for the students to understand means we would not be able to complete the modules in time.

    Consider this simple invisible button function added in AS2:

    on(Release) {
    with(“turret”){
    gotoAndPlay(“fire”)
    }
    }

    Even with no experience students of all ages could see exactly how their program was going to work and in 5 minutes would understand how implement it elsewhere in their game.

    Now make a similar function for AS3 and see how long you think it would take. If I am in fact wrong and there is a nice user friendly way to accomplish this sort of task in AS3 please shout up now while there is a chance to save the module.

    Love Alethea.

  22. drawk Says:

    Hey Alethea,

    You can still do lots of stuff the old way directly in the FLA. You don’t have to make things in classes although that would be a great learning experience. But you can still do it pretty simply. For instance a mouse click action on the stage.

    stage.addEventListener(MouseEvent.CLICK, onMouseClickEvent);
    function onMouseClickEvent(event:Event):void
    {
    trace(“mouse clicked on me”);
    }

    basically you can still do it quick and dirty but you need to be aware of the new event model. so for instance an onclick you need a mouse event.

    Lots of the old AS2 stuff works but when it comes to games the adding and removing of movieclips has changed to the addChild methods that does actually make things easier if you take a week or two looking at it. You will see some of the new methods are better and faster really when you understand them.

    You can see how good AS3 has been cleaned up from AS2 and a reference for mathching the old with the new here: http://livedocs.adobe.com/flex/2/langref/migration.html

  23. Lief Says:

    It was quite an unpleasant surprise to have three hours to sit down to make a quick and dirty flash project and spend the entire time going from site to site trying to find ready-made 100-line classes to do the thing that two lines of code used to do. I do this for fun on the side and don’t have time to put up with this shit. It’s really aggravating.

  24. drawk Says:

    Hey Lief,

    If you see the comments above it doesn’t have to be that complex that is mainly if you are making reusable buttons that you dont’ want to code again. You can still just put in the fla with minimal effort…

    addEventListener(MouseEvent.CLICK, onMouseClickEvent);
    function onMouseClickEvent(event:MouseEvent):void
    {
    trace(”mouse clicked on me”);
    }

    But AS3 is more programmer friendly mainly because it needed to attract the type of people that will make great libraries for creatives if you are more on the design than development side. Learning new things can suck but when you learn them they are a wall knocked down.

  25. Dan Trachtman Says:

    Whenever I run the example given, I get an error”packages cannot be nested”. I have it on the first frame. Whats the problem? thanks

  26. drawk Says:

    Dan,

    This should be an included .as or used as a document class, or an asset in your library referencing the external file in as3 compiled flash files.

  27. Agustin Says:

    It took me 5 hours of reading and 2 proyects (with a lot more hours of reading) to get going with AS3, I’m a designer and after understanding AS2 OOP and then migrating succesfully to AS3, i consider myself a self taught programmer, and every time I stumble upon a code like

    gotoAndPlay(2);
    and in the next frame
    gotoAndPlay(1);
    and in the third frame
    gotoAndPlay(2);
    ….

    I find things have become so much easier…

    And once you understand the basic structure of how classes asn AS3 work, you just adore how consistent it is and you can understand new classes very fast.
    Nowdays I don’t know how I managed with AS2, in the end, you think you write a lot more, but you relly don’t, belive me.
    Some apps made in AS2 took me about 1500 lines of code, now it is merely 200 (and a few reused classes of my own).

    I really love this new version of flash.

    sory for my english, I only know ActionScript english.

  28. ivan pedraza Says:

    All of that means that we as desginers are lelft out in this AS3 arena because we are not programmer and making something like a little button can be a daunting task. Moving from a to b or b to a in the time line? This is a utterly nonsense to me.

  29. Indy Says:

    I am trying to create a hotspot for my flash movie which is a slideshow using an XML file. The aim is if someone clicks on the movie it will go to a specifed URL.

    How do I create a dynamic hotspot in AS3? The hotspot will be a rectangle 320 x 204 in size (size of the stage).

    Ant help is appreciated.

  30. aaaaargh Says:

    So AS3 has totally alienated the people who were learning flash from the ground up…I have made many websites in flash 8 and it was very easy to do the basics such as gotoAndPlay etc etc…The whole idear behind Flash cs3 and AS3 was to make it better but in doing this they have cut out the majority of amateur flash designers who really aren’t great with code and just like the design aspects.Now myself and many other people are sitting looking at a load of codes scratching our head wondering how the hell we get our pretty little pages to goto the damn next scene/frame…I want to use flash cs3 but it appears you need a deep background in coding to do even the simple things…Such a shame….I for one am gutted.

  31. ландшафтный дизайн Харьков Says:

    ландшафтный дизайн Харьков
    ландшафтный дизайн Харьков (Jody)
    ландшафтный дизайн Харьков http://auto-imperia.biz/bitrix/rk.php?goto=http://dreamgarden.com.ua


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: