In this easy ActionScript lesson I will explain to you how to create professional, clean and polished buttons. No design tools will be used in this tutorial. Just pure ActionScript code! Please note that this is a lesson made for Flash 8 pro. You will learn how to:
- Create new movie clips from scratch,
- Create nested movie clips with ActionScript too,
- Create stunning gradients and other graphics via ActionScript,
- Import and embed fonts into Flash, understand how they work and add to the size of your SWF movie,
- Create dynamic text fields from scratch and format them using the myriad properties available in ActionScript,
- Import, create and apply filter effects to movie clips and text fields, and more.
Below are a few examples of the many buttons, menus and designs that you can create via ActionScript.
Creating empty movie clips with ActionScript from scratch
1 Open a new Flash document. Call the first layer actions. This is the only layer in your Flash document that you are going to need in this lesson. No others will be created. Lock this layer. You don't need to have it unlocked to be able to insert ActionScript code into it.
2 Select the first and only keyframe of this layer by clicking on it. This is where all the ActionScript code will be situated.
3 Open the Actions panel by selecting Window > Actions. Insert the following line of ActionScript code inside it (it is a single line of code — if your browser window is not wide enough, you may see it split into two lines):
this.createEmptyMovieClip("myButton1", this.getNextHighestDepth());
This line creates a movie clip instance from scratch. The createEmptyMovieClip
method (a method is a command, something that an object does) is used to create movie clips at runtime. At runtime means while the SWF movie is running, as opossed to working in Flash and creating movie clips with design tools.
The createEmptyMovieClip
method has two parameters inside it. The first one is the Instance name of the new movie clip. An Instance name is needed to control a movie clip via ActionScript, no matter if it was created programmatically or with design tools.
The Instance name of a movie clip must be unique. No two symbols in Flash can share the same Instance name, whether they are movie clips, buttons or text fields. Also, the Instance name can not contain special characters (like $, @, !, &, etc) or spaces. Stick to letters, numbers and the underscore ( _ ) and you'll be fine. While an Instance name can contain a number, it can not begin with a number (for example, button3
is fine, while 3button
is not). Keep in mind that ActionScript is a case-sensitive programming language, meaning that, for example, myMovieClip
, mymovieclip
and Mymovieclip
are all different Instance names.
As you have seen, the new Instance name is written between quotation marks, but only during the creation of the movie clip. Later, you will reference this movie clip by writing the Instance name without the quotation marks.
The second parameter is the depth assigned to the new movie clip. Think of the depth property of a movie clip as the third imaginary dimension on the screen. While you have two dimensions on your screen, the horizontal and vertical one, depth enables you to stack many movie clips on the screen, without having them interfere with one another. This is understandable, because if all movie clips shared the same depth, they wouldn't be able to display normally — in other words, it would be impossible to create more than one.
So, the depth of a movie clip is used by ActionScript in a similar way that layers are created in your Flash projects when you want to have graphics and other objects stacked one above the other. The thing to remember is that the main timeline (the root timeline, meaning the Flash movie itself) has the depth level 0 (zero). Depth levels are like invisible layers. Here is a nice graph explaining that:
You can specify the new depth as a number (1, 2, 3, etc) or you can use the getNextHighestDepth()
method which finds the next empty depth level and assigns it automatically to the movie clip in question. I recommend that you use the latter, because that will spare you from making errors, and also you won't have to keep track of the dpeth level numbers yourself.
If you do choose to assign numbers for depth levels, bear in mind that each movie clip must have its own unique depth. If you, say, assign a depth level of 14 to a movie clip and do the same thing for a movie clip that has been created afterwards, the second movie clip will completely replace the first one. Only one movie clip can be present on a single depth level. Also, each movie clip has its own depth level hierarchy, independent from the main timeline and other movie clips. This makes possible for the creation of other movie clips nested inside it. In its own depth level hierarchy, a movie clip has the depth 0.
You may have noticed the ActionScript keyword this
preceding both the createEmptyMovieClip()
and getNextHighestDepth()
methods. The keyword this
denotes (points to) the timeline it is situated on. So in the line of code that you just wrote, this
points to the main timeline, on which it resides. This means that the myButton1 movie clip will be created on the main timeline.
4 You can check if the movie clip was really created very easily: test your movie by selecting Control > Test Movie. The SWF file window ill appear, completely blank, which is normal.
5 Still in the testing window, select Debug > List Objects.
6 Flash will show you the objects that exist in this movie:
As you can see, the myButton1 movie clip is nicely displayed, and it resides on the main timeline (_level0).
The main movie clip was just made — think of it as the shell, the holder of all graphical content. You can start drawing the graphics dynamically inside it directly, but there is a small problem: I found out that you can't apply any filter to this movie clip that was created directly on the main timeline (if you find out how, leave a comment, I'll be glad to see how to pull that off :). So you have to make another one inside it, that will store all the graphics and will be able to have filters (like a shadow, blur, etc) applied to it.
7 Insert the following line of code right after the first one:
myButton1.createEmptyMovieClip("buttonBkg", myButton1.getNextHighestDepth());
This piece of code is very similar to the previous one: it creates an empty movie clip, but inside the myButton1
movie clip. As you can see, the ActionScript keyword this
was replaced by the main movie clip's instance name, myButton1
. The new movie clip, which I chose to call buttonBkg
(because it will hold the main button graphics — its background) has a new depth assigned to it, inside the myButton1
depth level hierarchy. You will now proceed to create graphics for this movie clip, using nothing but ActionScript.
Creating the main button shape at runtime with ActionScript
8 Following the existing code, insert the new one:
myButton1.buttonBkg.lineStyle(0, 0x820F26, 60, true, "none", "square", "round");
myButton1.buttonBkg.lineTo(120, 0);
myButton1.buttonBkg.lineTo(120, 30);
myButton1.buttonBkg.lineTo(0, 30);
myButton1.buttonBkg.lineTo(0, 0);
9 Test your movie (select Control > Test Movie). You will see a rectangle appear, placed right in the SWF's upper left corner.
This is perfectly normal. Flash places any new empty movie clips created via ActionScript in the main movie's upper left corner, which is the origin point of Flash coordinate system. Before I explain to you how the rectangle was created, you will move the myButton1 movie clip so that you can more easily see what you are creating.
10 Add the following two lines to the existing code (shown in bold):
this.createEmptyMovieClip("myButton1", this.getNextHighestDepth());
myButton1._x = 200;
myButton1._y = 100;
myButton1.createEmptyMovieClip("buttonBkg", myButton1.getNextHighestDepth());
myButton1.buttonBkg.lineStyle(0, 0x820F26, 60, true, "none", "square", "round");
myButton1.buttonBkg.lineTo(120, 0);
myButton1.buttonBkg.lineTo(120, 30);
myButton1.buttonBkg.lineTo(0, 30);
myButton1.buttonBkg.lineTo(0, 0);
These two lines move the myButton1 movie clip along the X and Y axis. If you test your movie now, you will see the rectangle appear somewhere around the middle of your SWF.
Let me show you now how the rectangle was made. Before any ActionScript drawing can be started, you must define the type of line with which Flash will draw:
myButton1.buttonBkg.lineStyle(0, 0x820F26, 60, true, "none", "square", "round");
Since you are creating graphics inside the buttonBkg
movie clip, you must reference it by writing myButton1.buttonBkg
, because it is nested within the myButton1
movie clip.
The next thing that comes is the lineStyle
method, which defines the type of line. There are many parameters inside it, I will list them here as they appear inside the method's parenthesis:
- Thickness. This is the line thickness, expressed in points. The value can be any number from 0 to 255. The value of 0 creates a hairline thickness, the finest possible line. Remember that this value must be defined, otherwise the line won't be drawn.
- RGB Color. This is a hexadecimal value, indicating the chosen line color. If you need a specific color, all you have to do is open any one of the color picker palettes in Flash, find the color you like and copy its hex code, then paste it here. Note that the color isn't written as in Flash working space (for example, green: #00FF00), but with a zero and a lowercase x following it: 0x00FF00.
- Alpha. This is the transparency of the line, which can range from 0 to 100. 0 indicates complete transparency (i.e. invisibility), while 100 is a completely opaque line.
- Pixel Hinting. This is a Boolean value (meaning either true or false). It tells Flash if the drawn lines should be placed on full pixels or not. A value of true is a good option for straight lines, but may make the graphics blurry if curves are drawn. Experiment and see what works best for you.
- No Scale. This is a String (text) value, which indicates if the lines that are going to be drawn should scale if the movie clip is scaled (scaling is like zooming in or out on an object). The possible values are:
"normal"
— this is the default value which always scales the thickness of the line."none"
— the line thickness never scales."vertical"
— line thickness won't be scaled if the movie clip is scaled only in the vertical direction."horizontal"
— line thickness won't be scaled if the movie clip is scaled only in the horizontal direction.
- Caps Style. This parameter tells Flash which type of cap to use at the end of the drawn lines. The possible values are:
"round"
"square"
"none"
- Here is a nice image explaining these values. Notice that in each case I drew a white line which has the same length as the thick red line below it, so that you can more easily see what caps are and how do they get rendered.
- Joint Style. This parameter tells Flash how to join lines at angles. The possible values are:
"round"
"miter"
"bevel"
This parameter basically boils down to this: If "round" is used, the corners will be rounded, if "miter" is used, the corners will be sharp and protruding, and the last value, "bevel", cuts off an angle.
There is one more parameter that can be used, miterLimit
. This last option comes into play only if the Joint Style was set to miter. Since it wasn't, you can leave it out.
Now that the line type was defined, the drawing can begin. Here is how the rectangle was drawn by Flash:
myButton1.buttonBkg.lineTo(120, 0);
myButton1.buttonBkg.lineTo(120, 30);
myButton1.buttonBkg.lineTo(0, 30);
myButton1.buttonBkg.lineTo(0, 0);
This is done via the lineTo
method, which uses coordinates to trace lines from point to point. The starting point is the upper left corner of the movie clip (this is the origin, where both X and Y coordinates equal zero). You can find more on this method in my tutorials that explains how to draw with ActionScript, since I don't wish to repeat myself here. A nice figure will quickly make clear how the rectangle was drawn:
You will see now how easy it is to fill this rectangle. Please continue.
Making a clean, polished linear gradient fill dynamically with ActionScript
11 Update your current code with these lines (shown in bold):
this.createEmptyMovieClip("myButton1", this.getNextHighestDepth());
myButton1._x = 200;
myButton1._y = 100;
var fillType:String = "linear";
var colors:Array = [0xFAD4DB, 0xEC748B, 0xC13A59, 0xA81230];
var alphas:Array = [100, 100, 100, 100];
var ratios:Array = [0, 126, 127, 255];
var matrix:Object = {matrixType:"box", x:0, y:0, w:80, h:30, r:90/180*Math.PI};
myButton1.createEmptyMovieClip("buttonBkg", myButton1.getNextHighestDepth());
myButton1.buttonBkg.lineStyle(0, 0x820F26, 60, true, "none", "square", "round");
myButton1.buttonBkg.beginGradientFill(fillType, colors, alphas, ratios, matrix);
myButton1.buttonBkg.lineTo(120, 0);
myButton1.buttonBkg.lineTo(120, 30);
myButton1.buttonBkg.lineTo(0, 30);
myButton1.buttonBkg.lineTo(0, 0);
myButton1.buttonBkg.endFill();
12 Test your movie by choosing Control > Test Movie. You should see a beautiful gradient fill appear, like the one shown in the screenshot below.
It looks really sleek, doesn't it? Very modern and Web 2.0-ish :). I will show you now how this works.
The method that triggers the filling of the rectangle is the beginGradientFill()
method, and must be placed before any lines are drawn with the lineTo()
method:
myButton1.buttonBkg.beginGradientFill(fillType, colors, alphas, ratios, matrix);
This method has several parameters that tell Flash what type of fill should be used, the colors involved in the gradient, their transparency values, placement within the gradient and how the fill should be laid out.
The method that closes the fill is the endFill()
method. This one comes after the last line of the rectangle was drawn and doesn't have any parameters, which is logical, because it only serves to close the fill.
myButton1.buttonBkg.endFill();
The values that dictate the appearance of the fill must be defined before the filling starts. Here they are:
var fillType:String = "linear";
var colors:Array = [0xFAD4DB, 0xEC748B, 0xC13A59, 0xA81230];
var alphas:Array = [100, 100, 100, 100];
var ratios:Array = [0, 126, 127, 255];
var matrix:Object = {matrixType:"box", x:0, y:0, w:80, h:30, r:90/180*Math.PI};
The fillType
variable is used to define the fill either as a linear or radial one. The colors
array is used to store the RGB hex values of all the colors that are going to be used in the fill. The alphas
array stores the transparency values of those colors. The ratios
array tells Flash how to place those colors within the fill.
The number of values in the alphas and ratios arrays must match the number of colors! If you fail to do that, you won't get your fill at all.
Last but not least, the matrix
object stores many values which define the type, placement, size and rotation of your gradient fill. For a more detailed explanation of this and all the preceding parameters of your fill, check out my lesson that explains the creation of gradient fills with ActionScript.
Creating a dynamic text field from scratch with ActionScript
13 Add these lines of ActionScript code right at the end of the existing one:
myButton1.createTextField("labelText", myButton1.getNextHighestDepth(), 0, 5, myButton1._width, 24);
myButton1.labelText.text = "webdesign";
Note that the above are two lines of code. The first one is very long, so it may be split into two rows in your browser.
If you test your SWF movie now, you will see the following:
That button label looks pretty crappy. It definitely needs to be embellished. But let me first explain you how it was created in the first place.
The createTextField()
method is used to make text fields on the fly. This method was used by the myButton1
movie clip directly and not by the buttonBkg
movie clip. The reason why is because you want the buttonBkg
movie clip and the labelText
text field to exist as independent objects inside the myButton1
movie clip, so that you can apply different filters to each one of them.
Here are the parameters of the createTextField()
method:
- The Instance name of the text field. The same naming rules apply to it as those mentioned for the movie clips, on the previous page of this tutorial. I chose "labelText" because it makes sense to me.
- Now comes the depth level of the text field. Again, I used the
myButton1.getNextHighestDepth()
construct to have Flash assign the text field the next unoccupied depth level inside the myButton1 movie clip. - The horizontal position of the text field (its x coordinate) is a number, which specifies the horizontal distance of the text field from the movie clip's origin point (0,0 — its upper left corner) in pixels.
- The vertical position of the text field (its y coordinate) is a number, which specifies the vertical distance of the text field from the movie clip's origin point (0,0 — its upper left corner) in pixels.
- The width of the text field is expressed in pixels. I used the text field's parent movie clip width to specify this value.
- The height of the text field is expressed in pixels.
To clarify the last four parameters (x, y, width, height) a little bit more, add this line to the end of your existing code:
myButton1.labelText.border = true;
Test your movie and you'll see a border appear around the text field.
If you watch closely, you'll see that the text field's left border coincides with the movie clip's left border. This is because the x coordinate of the text field is defined as 0. And the y coordinate places the text field 5 pixels from the movie clip's upper border.
The text field is wide as the movie clip, and a little less high than it. I made this on purpose because the text inside the text field isn't exactly in the middle of it and I don't want the field to come out of the button. You'll always have to play with these values a little bit, until you get what you want. And different values will be needed for different fonts and font sizes. There is no magical formula to adjust the size and position every single text field perfectly. Create a border, test your movie to see the results and start tweaking the values until you get them right.
You can remove the line of code that sets the border around the text now.
The label "webdesign" was inserted into the text field easily, by using its text
property:
myButton1.labelText.text = "webdesign";
OK, time to make it look professional now. This button has a file size of only 520 bytes! ActionScript rules! However, your SWF will gain in file size in a few moments, because you are going to import an entire font into it.
Importing an entire font into a Flash document
14 Open the Library by selecting Window > Library.
15 Click on the Library Preferences button (it is marked with a red arrow on the image below) and select New Font from the menu that shows up.
The Font Symbol Properties window will show up.
16 In the Font drop-down menu, select a font that you'd like to see on your button. I chose the Windows built-in Tahoma font, because it looks good to me on the button.
In the Name field, type a name for this font. You can type the same name as the font's if you like. However, if your font of choice is Times New Roman for example, write the name as TimesNewRoman. In other words, avoid spaces and special characters.
Leave the Bold, Italic and Bitmap text options unchecked and also don't change the Size option. You will manipulate the font size via ActionScript later. Click OK. The font will appear in your Library.
17 Right-click on the font inside the Library and select Linkage from the context menu.
18 In the window that appears, click the Export for ActionScript option to check it (the Export in first frame will automatically be checked too).
You can leave the Identifier name as it is, just make sure to write it exactly in the same way in your ActionScript code later. Click OK.
Importing a font into Flash means importing the information on every character defined inside it, such as rendering, spacing, etc. So, this can increase your final SWF's file size much, especially if complex fonts are being imported. In my case, the Tahoma font added 24 kilobytes to the size of my SWF. Pixel and bitmap fonts are cool, not only because they look that way, but also because they tend to be very simple and don't usually have as much characters defined inside them as other fonts might have — which results in smaller weight of your SWF movie.
Onwards! Let's format that button label now!
Embellishing a dynamic text field
19 Add these lines of ActionScript before the line in which the text field was created:
var myFormat:TextFormat = new TextFormat();
myFormat.align = "center";
myFormat.font = "Tahoma";
myFormat.size = 13;
myFormat.color = 0xFFFFFF;
You are creating here an instance of the TextFormat
object, which is used to change and set the various properties of a text field. I chose to call it myFormat
.
var myFormat:TextFormat = new TextFormat();
The four lines that follow the creation of the myFormat
TextFormat object define the following:
- The
align
property is used to align the text either to the: left, right, center or justify it. Centering it makes sense in this case, because the text will be the label of your button. - The
font
option defines the font to be used by the text field. Here, you must write the same exact Linkage name that you have given to your font in the Library in the previous step. If you don't do it, the text won't appear at all! - The
size
option is a numerical value that sets the font size for your text field. It is specified in points, not pixels. - The
color
option sets the color of your text field's text. This is a hexadecimal RGB value.
20 Add the four lines shown in bold after the line that sets the text "webdesign" in your text field:
myButton1.labelText.text = "webdesign";
myButton1.labelText.embedFonts = true;
myButton1.labelText.selectable = false;
myButton1.labelText.antiAliasType = "advanced";
myButton1.labelText.setTextFormat(myFormat);
21 Test your movie (choose Control > Test Movie). Now don't get alarmed if you see the following window appear and stay on your screen a little bit longer than usual:
Flash needs some time to export the movie which contains an imported font inside it. This is normal.
Once the short wait is over, you will see your new button in all it's glory, with the label rendered so good that it looks really amazing:
Mondo cool. The characters are rendered so sharply and smoothly, that it makes me cry :).
The piece of code that actually associates the font with the text field is the following:
myButton1.labelText.embedFonts = true;
The embedFonts
property of your text field set to true
makes this possible. Of course, a prerequisite for this is to have the font imported, a linkage name given to it and a TextFormat object created where you reference it.
Setting the selectable
property of your text field to false
disables the possibility of selecting its text:
myButton1.labelText.selectable = false;
I urge you to make this for text fields nested inside buttons, because it makes no sense to leave this option as true (the default value) if the object in question (a button) will be clicked by the user.
Now comes the antiAliasType
property of your text field, which, when set to "advanced"
does the rendering magic for your button's label:
myButton1.labelText.antiAliasType = "advanced";
Its default value is "normal". Don't use it for eye candy like this button.
And finally, the myFormat
TextFormat object gets associated with the text field, via the setTextFormat()
method:
myButton1.labelText.setTextFormat(myFormat);
Adding cool filter effects to your buttons
22 Add the three lines of code shown below above of all your existing code, before even the main movie clip was created:
import flash.filters.GlowFilter;
var labelGlow:GlowFilter = new GlowFilter(0xFFFFFF, .30, 4, 4, 3, 3);
var labelFilters:Array = [labelGlow];
...and add this ActionScript piece below the current code, after the text field was associated with the TextFormat object:
myButton1.labelText.filters = labelFilters;
Test your movie and see the result — a small but effective glow changes the visual aspect of the button's label completely:
This filter adds 77 bytes to your SWF movie :). Remember, it is the code for the filter that is being imported and not some graphics. The Flash Player installed on the user's computer is the one who interprets the filter code and subsequently applies the code to the object.
The first line (the one that begins with the keyword import
) imports the filter's class into your SWF.
The subsequent one creates a new GlowFilter
filter. The parameters that must be defined when a new glow filter is created are:
- color (RGB hex value).
- alpha (transparency, ranging from 0 to 1).
- horizontal blur, ranging from 0 to 255.
- vertical blur, ranging from 0 to 255.
- strength, ranging from 0 to 255.
- quality, ranging from 0 to 15. 1 is low quality, 2 is medium, while 3 is high. Any values above 3 increase the quality but also the rendering time.
There are two more options which can be used, but are not obligatory: inner and knockout. Both are Boolean values, which means that they can be set to either true or false. The inner glow effect doesn't make any significant change when applied to small font sizes like the one used in this tutorial. The knockout effect however, makes a big difference. Try the following:
- Set the inner option to false and the knockout option to true.
- Increase the alpha option to .90.
The chunk of code where the filter gets created should look like this...
var labelGlow:GlowFilter = new GlowFilter(0xFFFFFF, .90, 4, 4, 3, 3, false, true);
...and it will result in your button's label looking like this:
Interesting effect, huh? There is no end to what you can do with filter effects in Flash. Learn more by reading my lesson on the dynamic use of the blur filter.
Making the button clickable
This one is really easy. Add this at the end of your ActionScript code:
myButton1.onRelease = function() {
getURL("http://www.flashexplained.com/");
}
And you're done! The button is made clickable. It will get you to the home page of my website — change the URL to anything you like. But before wrapping up this lesson, I just want to show you the many cool effects and things that you can do with very little code. Have a look at this button:
And yes, it was done entirely with ActionScript! Even the shine in the upper portion of the button and the RSS icon! I won't post the code here — it has about 80 lines. But you can download it with the other source files at the end of this page :). The method used to draw rounded corners for this button is the curveTo()
method. The usage of this method was also explained in my basic drawing with ActionScript tutorial. As you can see, with ActionScript you can perform real wizardry!
To see how to move around stuff drawn in ActionScript, check out the Flash drawing API video lesson by Lee Brimelow. It is well worth the look.
The great thing about this is that you can create as many buttons as you like with these programming routines — even whole menus — I used a function to that end to create all the buttons shown at the top of the first page of this tutorial. That one is included with the downloads too.
Note: I have removed the fonts from some of the .FLA files so that you can download them quicker.
Download all the source files for buttons shown in this lesson
Your Welcome Thanks! For Teching That
awesome! thanks a lot!
TOTALLY AWESOME!!
WHAT A GREAT INPUT for my works
THANKS i learn a lot from this tutor
hm..
now i need to find another tutor
about roll over, roll out, and highlight ( after clicked )…
i got a very deathly dateline this time…
Thanks again
\(^o^)/
love you! 🙂
great lesson, thanks for sharing
very good tutorial, interesting & easy to understand
Thank you very very very much…………………..
It’s a great exercise in ActionScript, but the question no ever seems to answers, is, what’s the advantage?
All that Actionscript when I can just create a button on the stage in a fraction of the time.
Luka, i really need your help. I wanna click on a button and to go to a page. I have named all the instances and all but it doesn’t seem to work.
This is my code. WIll really appreciate any help given.
stop();
button1.onRelease = function(){
gotoAndStop (“page1”)
}
button2.onRelease = function(){
gotoAndStop (“page2”)
}
@shahid, thanks verrrryyy much…. your code makes mi video works!!!! 😀
[…] Luka. “How to Make Amazing Buttons in Flash Using ActionScript Only! | Flash Explained.” Flash Explained.com – Learn Flash Easily. 28 Oct. 2008. Web. 03 Dec. 2011. <http://flashexplained.com//actionscript/how-to-make-an-amazing-button-in-flash-using-actionscript-onl…>. […]
m working with action script 3.0.so this script ur telling for 2.0.so for AS 3.0 what will be the coding? only little modification s needed r should change the whole code ?
The link to the archive is DEAD !!!
Any mirror ???
Or is it possible to get it by mail ???
Thanks