Removing Things Using Code
by
kirupa | 15 April 2011
Have questions? Discuss this Flash / ActionScript
tutorial with others on the forums.
In an
earlier tutorial, you learned how to write some code and
dynamically add content either to your stage or another
movie clip. Adding items is only one part of the picture. At
some point, you may want to remove them as well. In this
tutorial, you
will learn how to write some code to remove visual elements
such as Movie Clips and Sprites.
Note Technically, you
will be learning how to remove DisplayObjects, but almost
everybody refers to them as MovieClips, Sprites, or a host
of other things that derive from it instead.
The following is an example that shows movie clips being removed
when you click on the minus button:
[ in
hindsight, this example is probably annoying ]
Keep clicking on the minus button to see more movie clips
being removed. Eventually, you will run out of movie clips
to remove. If you feel sad at the thought of that, don't
worry. Just refresh the page and all of the movie clips will
find their way back.
When you are adding things to display, have you ever
wondered how these things get stored internally? Well,
understanding a bit more about how that works will help you
greatly make sense of what actually happens when you add or remove
an element.
Internally, you have a list that deals with everything
related to displaying the things you see. This list is
affectionately known as the
display list:
Every visual element (aka things derived from
DisplayObject) you have is represented in this list. The
position of items inside this list is based on z-order.
While you probably know this from non-Flash experience, the
higher the number, the higher in the stack your object object will appear.
The previous diagram simplfied things greatly. The display list is by no means flat. Each entry in the
display list could be a container which, in turn, contains
children of its own:
In this diagram, squareBar is a container that has
other elements inside it. The technical term for container
is anything that derives from DisplayObjectContainer such as
a Sprite or MovieClip. Within each DisplayObjectContainer,
you have your own list of children whose position in the
list maps to z-order as well.
Ok, so that's all for the dissection of what goes under
the hood. Keep some of this under your hat as we start to look at how to remove elements.
The primary function you use to remove a
DisplayObject such as a MovieClip is removeChild.
There are two things to specify when using removeChild.
First, you call this function on the container the element
you wish to remove resides in. Second, you pass the element
you wish to remove as the argument to
removeChild.
Basically, it will look something like this:
- container.removeChild(elementToRemove);
In most cases, the container is commonly your
stage or another MovieClip instance
such as squareBar from the earlier example. Your elementToRemove
is anything that is based off of a DisplayObject
such as a Sprite, MovieClip, etc. that lives inside the
container you have your eyes on.
If you wish to remove an element at a particular z-index
from your container's list of children,
you can do that by passing the z-index value to the
removeChildAt function:
- container.removeChildAt(3);
In this example, you are removing the element at the
z-index of 3. All elements inside this container who have a
higher z-index than the one you just removed will have their
z-indexes appropriately reduced by 1. You will never have
gaps in your z-order.
One thing you need to ensure is that the element you remove
is something that actually exists in your container. The way
you can check for that is to use the
contains function:
- if
(movieContainer.contains(circle))
- {
- movieContainer.removeChild(circle);
- }
In our example, you are checking to see if your
circle movie clip exists
inside movieContainer. If it
exists, you go ahead and call removeChild on it. Poof - the
circle goes away. If that movie clip does not exist, then
you don't have to worry about removing it because it never
existed.
If you are using removeChildAt, you need to ensure that
the index value (which is your z-index value really) you are providing doesn't go higher than the
highest element in your list. There is a direct correlation
between the number of items in your list and the highest
index value allowed, so you can just check for the number of
items in your container before attempting to remove it by
index:
- if
(targetMovieClip.numChildren
>
elementIndex)
- {
- targetMovieClip.removeChildAt(elementIndex);
- }
The way you check for the number of items is by using the
numChildren property on your container object to return the
number of children it is currently hosting. If the number of
children inside the container is greater than the index
number (which is zero based) you are trying to remove, then
you can be assured that the element at the index you are
trying to remove can indeed be removed!
If
you want to remove all children from a container, the
easiest way is to go through each child in the container and
remove it individually:
- var
i:Number
=
targetMovieClip.numChildren;
- while
(i--)
- {
- targetMovieClip.removeChildAt(i);
- }
Notice that I am removing the elements in reverse order
from your container. The reason has to do with a subtle
detail I snuck in when describing the removeChildAt
function:
All elements inside this
container who have a higher z-index than the one you just
removed will have their z-indexes appropriately reduced by
1. You will never have gaps in your z-order.
When you remove an element from the bottom of your stack,
Flash goes through the stack and updates all of the z-index
values for the remaining elements to account for the removed
element.
By removing the element at the top, Flash doesn't have to
do any re-indexing because there are no elements that would
be affected when the element gets removed. This is a
performance optimization, but if you do not have that many
children or don't want to deal with the slight complexity in
your code, you can remove elements the more traditional way
instead:
- while
(targetMovieClip.numChildren
> 0)
- {
- targetMovieClip.removeChildAt(0);
- }
In this approach, you are just removing the bottom most
element until you have no more elements to remove.
Well, that's
all there is to removing elements so that you no longer see
them. When an element is removed, nobody quite knows what
happens to it. Some say it lives in a better place. Some
feel that it disappears into nothingness.
The truth is a
little bit in-between. If a removed element has no
references to it, such as through an array or something, it
will be garbage collected automatically once removed. If a
reference exists somewhere, your element will not be
visible, but it may still live in memory until any
references to it are fully removed.
If you want to see my final source code for the example
where you remove a hundred circles by clicking a hundred
times, download it from below:
Extract the files and open the removingMC.fla and Main.as
to run and examine the example for yourself.
Just a final word before we wrap up. If you have a question and/or want to be part of a friendly, collaborative community of over 220k other developers like yourself, post on the forums for a quick response!
|