Building Data-Driven Flash Movies - Splitting Up (
Page 7 of 8 )
At this point, your
Library should contain three symbols - "text" (the label), "circle" (the button)
and "item" (the container for both).
Drag
and drop an instance of the "item" symbol onto the Stage.
Use
the Modify -> Instance command to give this instance a name - I called mine
"itemInstance". This name will be used to reference the instance when creating
copies of it via the duplicateMovieClip() function.
Right-click
the first frame (this should be a keyframe), and add some ActionScript to it.
This will first make the instance invisible, and then load
the variables found at the URL "menu.php". Let's look at that script next:
// menu.php
// open connection to database
$connection = mysql_connect("localhost", "root", "secret") or die
("Unable to connect!");
mysql_select_db("menu") or die ("Unable to select database!");
// formulate and execute query
$query = "SELECT link, label FROM menu";
$result = mysql_query($query) or die("Error in query: " .
mysql_error());
if (mysql_num_rows($result) > 0)
{
// iterate through rows
while($row = mysql_fetch_object($result))
{
// build label string
$labelStr .= $row->label . "|";
// build link string
$linkStr .= $row->link . "|";
}
// print output as form-encoded data
echo "items=" . urlencode($labelStr) . "&urls=" .
urlencode($linkStr);
}
// close connection
mysql_close($connection);
?>
This script does the hard work of connecting to the database,
extracting the menu items and their corresponding links, and creating a
URL-encoded string that Flash can use.
It's important to note, at this
point, the format in which the data is output. All the menu labels are
compressed into a single string, separated by a pipe, and assigned to the
variable "items", while all the corresponding URLs are similarly concatenated
and assigned to the variable "urls".
Here's an example of what the output
of this script might look like:
All that's remaining is to write the ActionScript code that
reads these variables, parses them and uses them to create multiple instances of
the "item" symbol. Right-click the "item" variable, pop open the Actions panel,
and add the following code to it:
onClipEvent(data)
{
// split variables into array
items = items.split("|");
urls = urls.split("|");
// get position of template movie clip
yPos = getProperty("itemInstance", _y);
// iterate over array elements
for (i=0; i<(items.length-1); i++)
{
// clone movie clip and name it
duplicateMovieClip ("itemInstance", "itemInstance"+i, i);
// set position
setProperty ("itemInstance"+i, _y, yPos+i*50);
// set variables
set ("itemInstance"+i+".label", items[i]);
set ("itemInstance"+i+".url", urls[i]);
}
}
The onClipEvent(data) event handler is triggered whenever the
Flash movie completes loading the variables imported via loadVariables(). This
is necessary because Flash loads variables asynchronously, which means that it
doesn't wait for the variables to be fully loaded before proceeding to the next
statement of the script.
By wrapping the code in an onClipEvent()
handler, I'm ensuring that the it's executed only after the variables have
finished loading. This doesn't always work as advertised, though - keep reading
for a couple of caveats to this technique.
Once the variables have been
loaded, the split() function is used to break the concatenated label and link
strings into their constituent parts,
items = items.split("|");
urls = urls.split("|");
and a "for" loop is used to iterate over the resulting
arrays.
This "for" loop does a number of important things. First, it
creates a duplicate of the "itemInstance" movie clip, and gives it a unique name
by suffixing the array index to the name.
Next, it sets the vertical position of the newly-created
movie clip, via the instance's "_y" property. This position is calculated via a
simple algorithm, which allows each additional instance to be placed below the
previous one.
setProperty ("itemInstance"+i, _y, yPos+i*50);
Finally, the movie clip's "label" and "url" values are set
using the set() function; these values are used within the "text" and "circle"
symbols respectively (you remember I mentioned these on the previous page).
set ("itemInstance"+i+".label", items[i]);
set ("itemInstance"+i+".url", urls[i]);
These two lines of code set the newly-created menu item's
label and target URL respectively.
All that's left is to test the movie.
If all has gone well, this is what you should see:
It should be noted at this point that I sometimes encountered
problems while using the onClipEvent(data) event. In case you find that your
Flash movie isn't loading the variables correctly, you might want to consider
removing the
onClipEvent(data)
{
// code
}
handler from the movie clip instance, and instead add a new
keyframe (maybe around frame 3?) containing the following code:
// split variables into array
items = items.split("|");
urls = urls.split("|");
// get position of template movie clip
yPos = getProperty("itemInstance", _y);
// iterate over array elements
for (i=0; i<(items.length-1); i++)
{
// clone movie clip and name it
duplicateMovieClip ("itemInstance", "itemInstance"+i, i);
// set position
setProperty ("itemInstance"+i, _y, yPos+i*50);
// set variables
set ("itemInstance"+i+".label", items[i]);
set ("itemInstance"+i+".url", urls[i]);
}
This forces Flash to run the
split-into-array-and-create-duplicate-instances code whenever the movie plays,
instead of waiting for the event handler to be triggered. It's a somewhat
brute-force solution to the problem - the first option is far safer, not to
mention also being the one Macromedia recommends - which is why you should only
use it if you find yourself in dire straits.