Often in a Flash movie you will want to have a group of buttons (movieclips that control aspects of the movie) that act together in a coordinated way, with the same rollover/rollout activity on all of them except the currently selected (last clicked) button, which looks different from the others to indicate that it's selected.
This is easier to achieve if you use movieclip symbols for your buttons instead of button symbols. Above is an example of such a group of buttons: all of the buttons react to a mouseover by growing taller until they reach 180% of their original size, or less if the mouse is moved off first, in which case they then start shrinking til they reach their original size. The one exception to this is the 'currently selected' button, that is, the one that was most recently clicked. When a button is clicked it is immediately set to 200% of its original size and the previously selected button shrinks down to its original size.
All of that is achieved by doing the following:
In the example above, the buttons are named dogs, giraffes, bears, mice and birds (maybe each would start a related video or open a corresponding picture in an actual movie). Rollovers make the buttons grow and rollouts make them shrink, but the same code could be used for any other effect by just swapping other functions for the grow and shrink functions in this example.

To reproduce the sample above, draw a gray square, select it and convert it to a movieclip (Modify, Convert to Symbol) with a bottom center registration point as shown and any symbol name you want. Go back to the main movie (click Scene1), drag 5 copies of the movieclip onto the stage and name them dogs, giraffes, bears, mice and birds. Copy the code in the blue box below and paste it into frame 1 of the main movie and you should see the 5 buttons working the same as those above. Here are some notes and the code:
Notice that anything which needs to be done to all buttons in the array may be done with a loop in the form
for (var mc in groupinfo) { ... use groupinfo[mc] to access array element ... }
which applies all code in the code block (between curly brackets) to every element of the array. It does the same thing as a standard numeric-index-based for loop, except that it applies things in reverse (last element of the array gets done first). The equivalent numeric-index-based for loop would look like
for (var i=0; i < groupinfo.length; i++) { ... use groupinfo[i] to access array element ... }
Code in frame 1 of main movie to control group of buttons:
// create an array of all nav buttons in group
var groupinfo:Array = [birds, dogs, bears, giraffes, mice];
// create a variable to track the currently selected button
var activebtn:MovieClip;
// define handler function for rollovers
function grow() {
if (this._yscale < 180) {
this._yscale += 10;
}
}
// define handler function for rollouts
function shrink() {
if (this._yscale > 100) {
this._yscale -= 10;
}
}
// doRollOver: start the rollover action or process,
// unless the button is currently selected
function doRollOver() {
if (this != activebtn) {
this.onEnterFrame = grow;
}
}
// doRollOut: start the rollout action or process,
// unless the button is currently selected
function doRollOut() {
if (this != activebtn) {
this.onEnterFrame = shrink;
}
}
// doClick: 1) return previously selected button to normal, 2) show visual
// indication of selected button, 3) update activebtn
function doClick() {
activebtn.onEnterFrame = shrink; // return previously selected to normal
delete this.onEnterFrame; // stop activity on selected mc
this._yscale = 200; // change appearance of selected mc
activebtn = this; // update pointer to current selection
}
// assign functions to each event for each button in the group
function init() {
for (var mc in groupinfo) {
groupinfo[mc].onRollOver = doRollOver;
groupinfo[mc].onRollOut = doRollOut;
groupinfo[mc].onRelease = doClick;
}
}
init();
If you want the mouseover/mouseoff behavior of your buttons to be something you can create with a motion tween or a shape tween instead of with actionscript, you can still replicate the above behavior by creating two identical sequences within your button movieclip. For the sample above, I started with the same gray square movieclip as before and then edited it to add two sequences: one called grow, in which I dragged the upper right corner of the square further upward and to the right in the last frame and applied a shape tween to the first frame, and other called shrink with the same frames in reverse. Frame 1 and the ending frames of each sequence have stop() actions in them. This is a screenshot of the 4th frame of the grow sequence, eg:

Because each button movieclip contains its own sequences, we won't need onEnterFrame to control its behavior; instead we'll just send it to the right frame and make it play. To keep the action smooth between rollovers and rollouts, we'll first check to see what frame the movieclip is in currently and send it to the corresponding frame in the opposite sequence if necessary. Here's the code (to go in frame 1 of the main movie):
// create an array of all nav buttons in group
var groupinfo:Array = [birds, dogs, bears, giraffes, mice];
// create constants to define start and stop of grow and shrink sequences
// (shrink should be exactly the same sequence as grow, in reverse frame order)
var GROWSTART:Number = 10;
var GROWSTOP:Number = 19;
var SHRINKSTART:Number = 20;
var SHRINKSTOP:Number = 29;
// create a variable to track the currently selected button
var activebtn:MovieClip;
// doRollOver: start the rollover action or process,
// unless the button is currently selected
function doRollOver() {
if (this != activebtn) {
// if shrinking, send to corresponding frame in grow
if (this._currentframe > SHRINKSTART && this._currentframe < SHRINKSTOP) {
this.gotoAndPlay(GROWSTART + SHRINKSTOP - this._currentframe);
} else {
this.gotoAndPlay(GROWSTART);
}
}
}
// doRollOut: start the rollout action or process,
// unless the button is currently selected
function doRollOut() {
if (this != activebtn) {
// if growing, send to corresponding frame in shrink
if (this._currentframe > GROWSTART && this._currentframe < GROWSTOP) {
this.gotoAndPlay(SHRINKSTART + GROWSTOP - this._currentframe);
} else {
this.gotoAndPlay(SHRINKSTART);
}
}
}
// doClick: 1) return previously selected button to normal, 2) show visual
// indication of selected button, 3) update activebtn
function doClick() {
activebtn.gotoAndStop(SHRINKSTOP); // return previously selected to normal
this.gotoAndStop(GROWSTOP); // change appearance of selected mc
activebtn = this; // update pointer to current selection
}
// assign functions to each event for each button in the group
function init() {
for (var mc in groupinfo) {
groupinfo[mc].onRollOver = doRollOver;
groupinfo[mc].onRollOut = doRollOut;
groupinfo[mc].onRelease = doClick;
}
}
init();
You can download this fla for free with the link at right.
There are an infinite number of variations on this theme. Above is another example in which there are four different movieclips, each of which contains shape-tweened color transitions and a white background layer, with exactly the same frame sequence structure as shown above for example 2, running at a frame rate of 20fps. I changed GROW to FADEIN everywhere and SHRINK to FADEOUT, and added one change to the code, in the doClick function, to make the previously selected button fade instead of abruptly changing to its unselected state. Here's the code:
// create an array of all nav buttons in group
var groupinfo:Array = [birds, bears, bats, bunnies];
// create constants to define start and stop of fadein and fadeout sequences
// (fadeout should be exactly the same sequence as fadein, in reverse frame order)
var FADEINSTART:Number = 10;
var FADEINSTOP:Number = 19;
var FADEOUTSTART:Number = 20;
var FADEOUTSTOP:Number = 29;
// create a variable to track the currently selected button
var activebtn:MovieClip;
// doRollOver: start the rollover action or process,
// unless the button is currently selected
function doRollOver() {
if (this != activebtn) {
// if fading out, send to corresponding frame in fadein
if (this._currentframe > FADEOUTSTART && this._currentframe < FADEOUTSTOP) {
this.gotoAndPlay(FADEINSTART + FADEOUTSTOP - this._currentframe);
} else {
this.gotoAndPlay(FADEINSTART);
}
}
}
// doRollOut: start the rollout action or process,
// unless the button is currently selected
function doRollOut() {
if (this != activebtn) {
// if fading in, send to corresponding frame in fadeout
if (this._currentframe > FADEINSTART && this._currentframe < FADEINSTOP) {
this.gotoAndPlay(FADEOUTSTART + FADEINSTOP - this._currentframe);
} else {
this.gotoAndPlay(FADEOUTSTART);
}
}
}
// doClick: 1) save a reference to previously active button, 2) update activebtn,
// 3) turn off previously active, 4) turn on current active
function doClick() {
var prevbtn:MovieClip= activebtn;
activebtn = this; // update pointer to current selection
prevbtn.onRollOut(); // return previously selected to normal
this.gotoAndStop(FADEINSTOP); // change appearance of selected mc
}
// assign functions to each event for each button in the group
function init() {
for (var mc in groupinfo) {
groupinfo[mc].onRollOver = doRollOver;
groupinfo[mc].onRollOut = doRollOut;
groupinfo[mc].onRelease = doClick;
}
}
init();
You can get the fla for this example in navgroup.zip, available by subscription from the link at right.
That's nice -- our group of buttons now responds in a coordinated way to mouseovers. But buttons need to be able to do something when they're clicked too (like load and display a jpg as in the example below). Usually that something is specific to the button that's been clicked, so we really need a way to have the button save a bit of information about who it is and what it needs to do when it's clicked. To do that, we can set up the groupinfo array to hold that information. The information can then be used by the init routine to assign properties to each button so it will know what to do when clicked. For example, in the movie above, each button needs to know what jpg or swf to load when it is clicked. It also needs to know what text to display as its label.
Because there is no way to pass a parameter from a button to its onRelease function, you must save any information ahead of time that you want the button to be able to access when it is clicked. One way to do that is to assign properties to the button that contain that information, so it will be available for use when the button is clicked. This is what we do in the code below. You can also use built-in properties of the button, like _name or _currentframe, to get information about it.
In the code below, the groupinfo array is set up as an array of objects (so that many properties can be stored with each entry) instead of just an array of movieclip names. This allows us to specify the movieclip name, the button label text, and the swf to load for each button. As a side note, notice that the doRollOver and doRollOut functions have been defined so that they change the color of the text in the button instead of growing and shrinking the button as in the previous example.
To make this sample you need to create a one-frame movieclip with a background rectangle and a dynamic textfield named txt in a layer above it. The textfield text should be set to the color that you want to use for the non-rolled-over state (and have the little Ab button unchecked in the properties panel so that the text will not be selectable and won't interfere with the operation of the button). We'll assign the actual text for the button with actionscript, so you can leave the textfield blank. Place as many instances of the movieclip as you need on stage, giving each one an instance name (ours are named marigolds, daisies and crocus), and adding one line to the groupinfo array for each button to define its attributes. You also need a blank movieclip named holder for the pictures to load into.
This is the code for the sample above:
// groupinfo: array with information for all nav buttons in group
var groupinfo:Array = [
{mc:marigolds, display:"Marigolds", toload:"flowers/flower_yellow.jpg"},
{mc:daisies, display:"Daisies", toload:"flowers/flower_pink.jpg"},
{mc:crocus, display:"Crocus", toload:"flowers/flower_purple.jpg"}
];
// constants to define button text colors
var NORMAL_COLOR:Number = 0xcccccc;
var ROLLOVER_COLOR:Number = 0x00ff00;
var SELECTED_COLOR:Number = 0xffff00;
// activebtn tracks the currently selected button
var activebtn:MovieClip;
// mcl: MovieClipLoader instance to load external swfs/jpgs
var mcl:MovieClipLoader = new MovieClipLoader();
// doRollOver: start the rollover action or process,
// unless the button is currently selected
function doRollOver() {
if (this != activebtn) {
this.txt.textColor = ROLLOVER_COLOR;
}
}
// doRollOut: start the rollout action or process,
// unless the button is currently selected
function doRollOut() {
if (this != activebtn) {
this.txt.textColor = NORMAL_COLOR;
}
}
// doClick: show visual indication of selected button, update activebtn
// return previously selected button to normal
function doClick() {
activebtn.txt.textColor = NORMAL_COLOR; // turn previously selected button back
this.txt.textColor = SELECTED_COLOR; // change appearance of selected mc
activebtn = this; // update pointer to current selection
mcl.loadClip(this.pic, holder);
}
// initialize buttons: assign text, assign pic property, assign event handlers
function init() {
for (var element in groupinfo) {
// btn is a pointer to one of the nav buttons
var btn:MovieClip = groupinfo[element].mc;
// put right label onto each button
btn.txt.text = groupinfo[element].display;
// have each button remember which swf/jpg it is supposed to load
btn.pic = groupinfo[element].toload;
// assign functions to each event
btn.onRollOver = doRollOver;
btn.onRollOut = doRollOut;
btn.onRelease = doClick;
}
}
init();
The groupinfo array shown in the examples above can be further extended to hold any information which the button needs to know to correspond with other parts of the movie. For example, with separate holder movieclips for each external picture or movie file, the example above can be extended and used in combination with the sequential loading techniques discussed on this page to produce a movie in which a series of jpgs or swfs are preloaded and then faded in, each above the previous one, when the corresponding button is clicked.
In this example, the buttons have an additional disabled state defined (by color of the text). The button text is set to that color initially, and then changed to the 'normal' (active) button color once all pictures have been loaded. If you clear the cache and reload the page, you should be able to see the color change when loading is complete (depending on the speed of your connection). The fla for this example is available by subscription from the link at right.
last update: 13 May 2006
Discussed on this page:
control group of nav buttons, show state of selected control, controls that grow, controls with different labels, array to hold group information, nav buttons and slideshow
Files:
Sequence-based button group
buttongroup_sequences.fla
(free download)
Button group for slideshow
Animals button group
In navgroup.zip, password required
Subscription:
A password may be obtained by subscription
An access password will be emailed to the address you specify within 24 hours of receipt of payment, and will remain active for 30 days thereafter. A list of all files currently available at the site may be viewed here.