Building Data-Driven Flash Movies

Hook your Flash movie clips up to a database.

The Next Step

So you've figured out the basics of the Flash toolbox, created your first tween, and added some wild animation to your Web site. You've built animation clips with fading reverbs, and created buttons which change shape as you mouse over them. And you're wondering what to do next.

Well, wonder no more.

While there's a lot you can do with the tools Flash gives you, it's when you hook it up to the wild and wacky world of the Web that you truly begin to appreciate the power (and genius) of the application. Today's Web is built around dynamic, data-driven Web sites, and Flash, which comes with built-in capabilities to read data from a variety of data sources, is well-suited to it.

The new data retrieval features in Macromedia Flash 5 (and better) allow developers to retrieve information from server-side databases and use this information to dynamically construct animation clips on the fly. As you might imagine, this opens up new possibilities for the creative Web developer, and sets the tone for a new generation of smart, dynamic and very cool Web applications.

In this article, I'm going to give you a little preview, demonstrating how Flash can be hooked up to a MySQL database to dynamically construct database-driven animation clips. Most of these examples are fairly simple - you might even find them too simple - but they should serve as a gentle introduction to the new capabilities Flash gives you, and perhaps even help to answer that "what next?" question by sparking some ideas in that tangled web of neurons you call a brain. So strap yourself in tight - this is gonna be an exciting ride!

Message In A Bottle

Before we get started with building a database-driven animation clip, you need to know a little theory.

The first - and most critical - thing you need to know is that there is never direct communication between Flash and a database. A Flash movie can never talk directly to a database server - there is always a third party involved. This third party takes care of building and transmitting the query from the movie to the database, and retrieving and massaging the results into a format that is usable by the movie clip.

This third party's role is usually played by a server-side application such as Perl, PHP, ASP, ColdFusion et al.

In order to better understand this, let's consider a simple example. Pop open Flash, create a new movie and then create a new Graphic symbol. Name it "message".

Now, in the Symbol Editor, create a text box with the Text tool (hit A on the keyboard). Use the Window -> Panels -> Text Options panel to turn it into a dynamic, multi-line text box.

While you're there, also set a variable name for the newly-minted dynamic text box - this is the variable that Flash will look for when the time comes to populate the text box. I've used the variable name "msg".

Back in the Scene Editor, drag and drop a copy of your newly-created symbol onto the Stage.

In the timeline, select the first frame (this should be a keyframe), right-click it and pop up the Actions dialog box. On the left-hand side of the Actions panel, look in the "Basic Actions" sub-category and select the loadVariables() function. This ActionScript function allows you to load variables into the Flash movie from an external URL - more on how this works later.

The lower half of the Actions panel should prompt you to enter some parameters for this function - specifically, the URL to get the variables from. For the moment, let's assume that the variables will be loaded from the URL "message.txt" - specify this in the lower half of the panel, as shown below.

The file specified as the variable source must contain data in the MIME format "application/x-www-urlformencoded" - that is, a series of variable-value pairs separated by ampersands (&). Here's what my copy of "message.txt" looks like:

msg=Welcome to the wonderful and wacky world of dynamic data sources!

Obviously, this file should be stored in the same place as the Flash movie (you can store it elsewhere too, just remember to alter the URL supplied to loadVariables() appropriately).

Now, when the Flash movie plays, the contents of the file "message.txt" will be read, converted to variables and used within the Flash movie. Take a look:

Wanna change the message? Just alter the contents of "message.txt",

msg=Look, Ma, no hands!

and watch in amazement as your Flash movie changes as well!

No Hands

Obviously, that was a very primitive example, though one that did demonstrate the concept of integrating data from an external source with a Flash movie. Now, how about a twist?

Let's suppose I modify the Flash file above so that the call to loadVariables() loads variables from a server-side script ("message.php"), rather than a static text file.

loadVariablesNum ("http://localhost/message.php", 0);

This "message.php" script contains code to retrieve a message (either from a database or other data source) and output it in the format Flash needs. Here's what the script looks like:

<?php
// message.php

// open connection to database
$connection = mysql_connect("localhost", "root", "secret") or die("Unable to connect!");
mysql_select_db("data") or die("Unable to select database!");

// formulate and execute query
$query = "SELECT message FROM message_table";
$result = mysql_query($query) or die("Error in query: " . mysql_error());

// get row
$row = mysql_fetch_object($result);

// print output as form-encoded data
echo "msg=" . urlencode($row->FirstName);

// close connection
mysql_close($connection);
?>

This should be fairly simple to understand, even if you've never programmed in PHP before. Very simply, I'm opening a connection to a MySQL database, running an SQL query to retrieve the contents of the "message" table, and displaying that content as form-encoded data.

Here's an example of what this script might output:

msg=Happy+Father%27s+Day%21

Now, when you run the Flash movie, it will access the specified URL, retrieve the form-encoded variable-value pair, parse it, and insert the variable values into the movie. Which is why the Flash movie will look like this:

Any change to the database record will be immediately reflected in the Flash file - with zero changes required to the Flash source.

In case you don't want to use a database as your data source, you can even run a shell command and send the output of the command to the Flash movie for display. Consider this variant of the script above, which displays the output of the "fortune" program (a new message every time) whenever the Flash movie is played back in your browser.

<?php
$output = `/usr/games/fortune`;
echo "msg=" . urlencode($output);
?>

No News Is Good News

Now, you can develop some pretty cool applications with power like this...and one of the coolest (and easiest) is a dynamic news ticker, updated from a MySQL database. Let's see how.

First, pop open a new Flash movie and create a dynamic text box symbol, in the manner described on the previous page. Call it "ticker", and name the variable which will contain the data for the text box "content".

Format the appearance of the text box, by adjusting the values in the Window -> Panels -> Text Options and Window -> Panels -> Character dialog boxes. I used a white Arial font, size 12, right-aligned.

Next, we need to create a motion tween to move the text box horizontally across the bottom of the movie. Insert an instance of the newly-minted "ticker" symbol into your movie clip, outside the lower right edge of your movie clip.

Insert a new keyframe in your timeline somewhere around frame 40, and move the symbol instance all the way across to the other edge of the movie clip.

Right-click anywhere between the two keyframes in the timeline and insert a motion tween.

Test your movie. You should see the symbol instance float horizontally across the bottom of the screen.

Download: x1.swf

Of course, it doesn't contain anything yet - which makes it fairly useless. Let's rectify that next. Right-click the first keyframe and insert some ActionScript.

loadVariablesNum ("http://localhost/ticker.php", 0);

This tells Flash to load variables generated by the server-side script "ticker.php" into the movie, and use them wherever required. Let's look at that script next.

Alien Invasion

Let's assume that the news headlines to be displayed are stored in a database table which looks something like this:

+---------------------+------------------------------------------------
| date                | body
+---------------------+------------------------------------------------|
2001-12-20 10:16:48 | An extra-terrestrial materialized outside the rabbit hole today. Calling itself ALICE, this ET claims to have come from a planet named ...                  |
| 2001-12-20 10:20:58 | Executives at Robots'R'Us today announced the launch of their latest multi-function household assistant, IDA (I'll Do Anything), the most sophisticated ... |
+---------------------+------------------------------------------------

The script "ticker.php" needs to connect to this database and extract the five most recent records from it. This data can then be converted into form-encoded data and picked up by the Flash movie.

Here's the code to accomplish this:

<?php
// ticker.php

// open connection to database
$connection = mysql_connect("localhost", "root", "secret") or die("Unable to connect!");
mysql_select_db("news") or die("Unable to select database!");

// formulate and execute query
$query = "SELECT body FROM stories ORDER BY date DESC LIMIT 0,5";
$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 headline string
        $str .= $row->body . " * ";
    }

    // print output as form-encoded data
    echo "content=" . urlencode($str);
}

// close connection
mysql_close($connection);
?>

Again, this is fairly simple. The script first connects to the database server, selects a database and executes an SQL query to select the five most recent stories from the system. A "while" loop is used to iterate over the returned resultset, with the content of each record appended to a single string, separated by an asterisk.

Once the entire string has been constructed, it is encoded via PHP's urlencode() function and sent to the standard output, where it can be picked up by the Flash movie.

If PHP isn't your cup of tea, you can also do this in Perl - here's the code you'll need:

#!/usr/bin/perl

# load module
use DBI();

# connect
my $dbh = DBI->connect("DBI:mysql:database=news;host=localhost", "root", "secret", {'RaiseError' => 1});

# execute query
my $sth = $dbh->prepare("SELECT body FROM stories ORDER BY date DESC LIMIT 0,5");
$sth->execute();

print "content=";

# iterate through resultset
while(my $ref = $sth->fetchrow_hashref())
{
        print "$ref->{'body'} * ";
}

# clean up
$dbh->disconnect();

Here's what the output of the script might look like:

content=Executives+at+Robots%27R%27Us+today+announced+the+launch+of+their+latest+multi-function+household+assistant%2C+IDA+%28I%27ll+Do+Anything%29%2C+the+most+sophisticated+...+%2A+An+extra-terrestrial+materialized+outside+the+rabbit+hole+today.+Calling+itself+ALICE%2C+this+ET+claims+to+have+come+from+a+planet+named+...+%2A+

With the server-side component in place, and the Flash movie all prepped and ready to go, all that's left is to test the movie again. This time, the text box should be dynamically populated with the results of the SQL queries in the script above, and should display this data as a scrolling news ticker along the bottom of the movie.

Download: x2.swf

As the database is updated with new stories, the Flash file will automatically read and display them via the server-side script "ticker.php". Pretty cool, huh?

What's On The Menu?

Another, more advanced example involves constructing a Flash menu dynamically, from the information in a database. This allows you to build menus that can grow and shrink automatically, as the information in the database changes, and it's a guaranteed entry into Flash geekdom.

The process is fairly complicated, so let me run you through a quick theoretical overview before we get started. Most of the work here happens via an ActionScript function named duplicateMovieClip(), which makes it possible to programmatically clone a Flash movie clip symbol. So, if you had a single movie clip symbol, representing a single menu item, you could combine the duplicateMovieClip() function with a loop to spawn numerous copies of that single menu item, and thereby build an entire menu dynamically.

This might seem a little far-fetched, but it works pretty well...as you'll see very shortly. First, though, let's get all the pieces together.

Let's assume that the data to be used for the menu is stored in a MySQL database table named "menu", and that it looks like this:

+-------------------------------------+--------------+
| link                                | label        |
+-------------------------------------+--------------+
| http://www.melonfire.com/services/  | Services     |
| http://www.melonfire.com/company/   | Company      |
| http://www.melonfire.com/mcenter/   | Media Center |
| http://www.melonfire.com/account/   | Your Account |
| http://www.melonfire.com/community/ | Community    |
+-------------------------------------+--------------+

Pop open Flash, create a new movie, and create a couple of new symbols. The first one is a graphic symbol containing a single-line dynamic text box - name the symbol "text" and the data variable "label".

At a later stage, I'll be using ActionScript to set a value for this "label" variable.

Next, create a button symbol, one which includes keyframes for up, over and down states. Here's what mine looks like:

Download: x3.swf

Name this button symbol "circle".

In case you're wondering how I created this, it's fairly simple. In the Symbol Editor, use the Oval tool to create a hollow circle (remember to make the fill colour transparent to achieve the hollowed-out effect) for the Up state.

Next, insert a new keyframe for the Over state, and place a smaller inner circle within the outer one. Make sure that this one has a fill colour (I've used red).

Finally, create a movie clip symbol named "item".

This symbol is what I'll be using to generate the menu items in my dynamic Flash menu. It should contain both a button (which the user can click to go to a specific URL) and a label (which describes the menu item). You've already created both these components; all you need to do is drag and drop them from the Library into the movie clip Symbol Editor.

Yes, that's right - your movie clip symbol is made up of two other symbols. No, I'm not smoking a controlled substance - all will become clear shortly.

Now, right-click the "circle" symbol in this movie clip and insert some ActionScript:

on (release) {
    getURL (url);
}

At a later stage, I'll be using ActionScript to set a value for this "url" variable.

Splitting Up

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.

itemInstance._visible = false;
loadVariablesNum ("http://localhost/menu.php", 0);

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:

<?php
// 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:

items=Services|Company|Media+Center|Your+Account|Community|&urls=http%3A%2F%2Fwww.melonfire.com%2Fservices%2F|http%3A%2F%2Fwww.melonfire.com%2Fcompany%2F|http%3A%2F%2Fwww.melonfire.com%2Fmcenter%2F|http%3A%2F%2Fwww.melonfire.com%2Faccount%2F|http%3A%2F%2Fwww.melonfire.com%2Fcommunity%2F|

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.

duplicateMovieClip ("itemInstance", "itemInstance"+i, i);

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:

Download: x4.swf

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.

Linkzone

And that's about all I have time for. In this article, I introduced you to data-driven Flash applications, demonstrating how you can use a database and a server-side script in combination with the new data retrieval capabilities in Flash 5 to dynamically construct Flash movies. I also showed you a couple of simple examples, including a database-driven Flash news ticker and a dynamically-constructed Flash menu.

However, building Flash movies from a database is only the tip of the iceberg. Flash comes with a number of tools that allow you to add new types of interactivity to your movies, including creating forms capable of accepting user input and parsing XML data sources. I'll be discussing these capabilities in detail in upcoming articles - but until then, chew on these links, and I'll see you soon!

Macromedia's Flash resource center, at http://www.macromedia.com/software/flash/productinfo/tutorials/

Flash 101, at http://www.melonfire.com/community/columns/trog/archives.php?category=Flash

FlashKit, at http://www.flashkit.com/

Virtual-FX, at http://www.virtual-fx.net/

Webmonkey's Flash section, at http://hotwired.lycos.com/webmonkey/multimedia/shockwave_flash/

Note: All examples in this article have been tested on Macromedia Flash 5.0. Examples are illustrative only, and are not meant for a production environment. Melonfire provides no warranties or support for the source code described in this article. YMMV!

This article was first published on11 Jul 2002.