Build a Better Charting Engine Using Flash and XML

hen you think of the phrase “charting on the Web”, you probably think of COM components, .NET assemblies, or extensions (like Office Web Extensions). While these are great ways to chart your data, they do put a strain on the system when you need to chart data for thousands of concurrent users. They also come with installation hassles and high-priced licensing policies. You might also think of plain “nested-table” HTML charts, but these don’t really make a very big impact on the end-user.

There is an alternative solution that combines good aesthetics with rich content. Macromedia Flash can help you create animated, data-driven charts. Flash’s built-in scripting support (ActionScript) allows you to deliver great-looking interactive content.

In this article, you’ll learn how to build a Flash movie that takes XML data from server-side script (ASP, in this example) and uses it to render an animated column chart. The chart, shown in Figure 1, will be called “Flash Column Chart.”

Figure 1. Flash Column Chart: This is the Chart you’ll be creating.

Formalities First
This article is geared toward developers who have a working knowledge of ASP or ASP.NET and a basic knowledge of Flash MX and ActionScript (like handling the Flash MX Authoring Interface, Dragging and Placing Form Elements, naming them etc.). Obviously, you’ll need Macromedia Flash MX to open and modify the .fla files. Download a Macromedia Flash MX 30-day trial here.

Even if you’re a newbie to Flash, you can simply download the support files of this article and use the completed .swf for your charting purposes without having to peep into how this component was made. However, Flash MX has a very lucid and intuitive interface, so it would not take much to get started with it.

Figure 2. An Overview: Here’s a glimpse of what the entire data communication model might look like.

Lights! Camera! ActionScript!
Figure 2 shows the entire data communication model for this chart. The HTML wrapper page which embeds the Flash Column Chart provides the full XML data to Flash Column Chart:

 ...... 

Flash Column Charts picks this data up, parses it, and renders the chart.

The XML Structure
The Flash column chart only accept XML in the following format:

                         

The element is the root element (i.e., the document element). has a number of properties that help configure the chart’s layout by specifying the aesthetic settings.

To specify the data settings, use elements. elements, as in the XML code above, are the child elements of the element. For each piece of data you wish to plot, you have to specify a element. Click here for a list of element attributes.

The Flash Movie for the Chart
Open up FCChart.fla using Flash MX. You’ll be presented a movie with the dimensions 350×280 pixels?this is the size of the chart that you’ll be creating. Now, switch to the scenes dialog box (Modify?>Scene).

The Flash movie has two scenes: Loading and Chart. The Loading scene contains the pre-loader for the movie. A pre-loader is a sequence of text/graphics that is shown to the viewer until the entire .swf file (the compiled Flash movie) has been downloaded into his machine. Click here to learn more about making a pre-loader.

Figure 3. The Chart Scene: This scene shows all of the elements, ActionScripts, and objects that drive the chart.

Use Edit Scenes?>Chart to switch to the Chart Scene. Here you see all of the elements, ActionScripts, and objects that drive the chart. In this scene, you’ll need to:

  • Declare global functions and constants which are used throughout the chart for general purpose.
  • Request the XML Data from the HTML page and check if it’s valid.
  • Parse the data and store it in various objects/variables within the Flash Movie. Or display appropriate error message stating that the XML was invalid.
  • Calculate the various aspects of the chart: limits, positions of various elements, height of each of the column, etc.
  • Render the chart.

Figure 3 shows how this scene should look.

As you can see, the Chart Scene has six layers, which we’ll examine more closely.

The Chart Scene’s Layers

  • Global Functions and Constants: This layer contains the global functions and constants to be used generally throughout the chart. Open up the Actions Panel for the keyframe on this layer and you’ll see the same code as in Listing 1.

    All the ActionScript contained in this frame belong to six functions. Click on each function for an overview:

  • Actions: All the Actions defined in this article are contained in the Actions Layer. This layer also contains all of the ActionScript required for building the chart.
  • Figure 4. The Labels Layer: This layer consists of four blank keyframes that contain their own names.
  • Labels: This layer consists of four blank keyframes that contain their own names (Figure 4). When you design a Flash application, it’s a good idea to name all the keyframes on a layer to simplify ActionScript navigation.
  • Column: This layer is used to manipulate the shapes of the data once it’s rendered.
  • Rendering Chart Message: This layer shows a rendering chart message while the XML doxument is being parsed and the various co-ordinates of the chart elements are calculated. Instead of a plain textbox, you can also use animated graphic sequences or something more pertinent to your Website’s theme.
  • XML Error Message: The layer is invoked when there is an error in the XML document supplied by the server. It displays the appropriate error message and stops the play of the movie. Again, you can customize this layer with your own graphics, animation, etc.

Loading the XML Data
There are three steps involved in loading XML data:

  1. Request XML from the HTML page.
  2. Validate the XML document.
  3. Parse the data and store into local objects, arrays, and variables.

To load the XML data, open the Actions Panel for Frame 1 on the Actions layer. This keyframe contains all the ActionScript required for loading XML:

//XML Object xmlData will store the entire XML Documentvar xmlData = new XML();

Create an XML object to store the data named xmlData:

//Request the data from the HTML Page and store it in the xmlData XML object. xmlData.parseXML(_root.data);

Request the XML data from the HTML page and use the parseXML method of the XML object to store it in the XML object. The data is provided to the chart in the following form:

... Other Contents ......

Use _root.data to access the HTML page in Flash:

//Check for error in XML documentif (xmlData.status != 0) {//Means, there was an error in the XML document//- so redirect to frmXMLErrorgotoAndPlay("frmXMLError");}

To check for errors in the XML document, use the XML doc’s status property. When the XML document is perfectly valid, the status becomes 0.

If the status isn’t 0, move the control to the XML error frame (frmXMLError) to display the appropriate error message. When the data has been validated, move on to step three.

Parsing the XML Data
When XML document has been loaded, retrieve the data from the XML document and store it in local data storage objects. First, you need to initialize the local objects, arrays, and variables used to store the data. These are defined in Frame 1 of the Actions layer. Basically, there are three objects used to store data:

  1. _global.data: This stores instances of the _global.dataSet object (discussed just below). The array has n rows, where n is the number of data sets passed in the XML document.
  2. _global.dataSet: This stores all the external (supplied by the XML doc) and internal (calculated by the chart) values for a particular dataset. The values include name, value, color, and link of a set along with its width, height, and x and y positions.
  3. _global.chartParams: This stores the external (supplied by the XML doc?e.g., bgColor) and internal (calculated by the chart e.g., canvas width) parameters of the chart.

Listing 2 shows the entire code for initialization.

Now, parse the data. Declare the local variables you will use while parsing:

//chartNodes will contain the child nodes of the XML Doc passed to it.//setNodes will contain the  elements and their attributesvar chartNodes, setNodes;//Temporary variables to store the set attributesvar setName, setValue, setLink, setColor;chartNodes = new Array();setNodes = new Array();

Next, get a reference to the node i.e., the root element or document element of the chart:

chartNodes = xmlData.childNodes;

You also need to declare a global counter variable to keep a track of how many datasets have been passed to the chart via the XML:

_global.chartParams.num = 0;

Now, iterate through the first level nodes of the XML document and look for the element:

for (j=0; j<=chartNodes.length; j++) {	//Check if the node Name is Chart	if (chartNodes[j].nodeName.toUpperCase() == "CHART") {

Once the element has been found, extract its attributes and store it in the global object _global.chartParams (Listing 3).

After you've extracted all of 's attributes, extract all the elements and their attributes. Get a reference to 's child nodes:

//Now, get the  nodes		setNodes = chartNodes[j].childNodes;

Iterate through the extracted nodes, look for nodes, and extract their attributes:

for (k=0; k<=setNodes.length; k++) {			//If the node name is Set i.e., a chart data set, then we retrieve	    	//and collect the values			if (setNodes[k].nodeName == "set") {				//Get the x-axis name				setName = setNodes[k].attributes.name;				//Get the value				setValue = setNodes[k].attributes.value;				//Get the color - set the default color as 0099FF				setColor = getPrimaryValue(setNodes[k].attributes.color, "0099FF");				//Get the link				setLink = setNodes[k].attributes.link;				//Now, only if we have been specified the setValue, we add this				if (setColor != undefined && setColor != null) {					//Increment the counter					_global.chartParams.num++;					//Create an object in _global.data to represent this 					_global.data[_global.chartParams.num] =					 new _global.dataSet(setName, setValue, setColor, setLink);				}			}		}	}

Finally, clean up the temporary objects and move to the next frame.

//Delete the temporary elements now	delete xmlData;	delete setNodes;	delete chartNodes;}//Now, move ahead to the next keyframeplay();

The entire code to load and parse the XML data is shown in Listing 4.Calculations for the Chart
The chart calculations basically determine the size and scope of the chart. You can find all the ActionScripts for the necessary calculations in Frame 2 of the Actions Layer:

  1. Defining co-ordinate constants.
  2. Calculating the upper and lower limit for the chart.
  3. Calculating the zero plane position of the chart.
  4. Calculating the various co-ordinates of the chart elements.

Click each task for a deeper explanation.

Rendering the Chart
This involves rendering the following chart elements:

  • Background
  • Canvas
  • Chart labels?like caption, limit textboxes, x-axis textboxes, etc.
  • Horizontal Divisional Lines
  • Columns
  • Zero Position Line

The background of the chart is basically a rectangle of the full width and height of the chart. Use the code below to create the background. It invokes the drawRectangle function.

drawRectangle(getLevel(), 0, 0, chartParams.CChartWidth, chartParams.CChartHeight, chartParams.bgColor, chartParams.bgColor, 1, 100, 100);

Use the following code to draw the canvas:

drawRectangle(getLevel(), chartParams.CCanvasStartX, chartParams.CCanvasStartY,chartParams.CCanvasStartX+chartParams.CCanvasWidth, chartParams.CCanvasStartY+chartParams.CCanvasHeight,chartParams.canvasBrdrColor, chartParams.canvasBgColor, 1, 0, 100);

Next, render the chart caption textbox and upper and lower limit textboxes. Use the createText method:

//Chart CaptioncreateText(chartParams.caption, _global.chartParams.CCanvasStartX+(_global.chartParams.CCanvasWidth/2),_global.chartParams.CCanvasStartY-_global.chartParams.fontSize, _global.chartParams.font, _global.chartParams.fontSize,_global.chartParams.fontColor, true, "center", getLevel());//***** Render the chart limit textboxes ******////First, we create the upper limit textboxcreateText(chartParams.upperLimit, _global.chartParams.CCanvasStartX, _global.chartParams.CCanvasStartY,_global.chartParams.font, _global.chartParams.fontSize, _global.chartParams.fontColor, true, "right", getLevel());//Now, create the lower limit textboxcreateText(chartParams.lowerLimit, _global.chartParams.CCanvasStartX,_global.chartParams.CCanvasStartY+_global.chartParams.CCanvasHeight, _global.chartParams.font,_global.chartParams.fontSize, _global.chartParams.fontColor, true, "right", getLevel());

Now, draw the horizontal divisional lines and set the text for each of the divisional line.

//***** Divisional Lines ******//var verticalPos, divValue;verticalPos = chartParams.CCanvasHeight/(chartParams.numDivLines+1);for (i=1; i<=chartParams.numDivLines; i++) {	//Draw the divisional line	drawLine(chartParams.CCanvasStartX, chartParams.CCanvasStartY+(verticalPos*i), chartParams.CCanvasStartX+chartParams.CCanvasWidth, chartParams.CCanvasStartY+(verticalPos*i), 1, chartParams.divLineColor, 100, getLevel());	//Also set the value - round it off to 2 places	divValue = Math.formatDecimals(chartParams.upperLimit-(i/(chartParams.numDivLines+1)) *chartParams.yAxisInterval, chartParams.decimalPrecision);	//Create the text	createText(divValue, _global.chartParams.CCanvasStartX, chartParams.CCanvasStartY+(verticalPos*i), _global.chartParams.font, _global.chartParams.fontSize, _global.chartParams.fontColor, false, "right", getLevel());}

Next, switch to the Column layer. In this layer, you'll find a single column off the stage. The column's instance is named as MovColumn and it's object name is MovScriptedColumn. The column takes in the following parameters and sets itself accordingly:

  • fcHeight: Required height of the column (in pixels).
  • fcAnimation: Flag which tells whether to animate the column or not.
  • fcColor: Color of the column.
  • dataIndex: Index of this column (i.e., which this column represents)

The chart rendering code duplicates this column for all the data sets and then passes the required height, color, and data index. You also need to set the x and y position the column of each dataset. Lastly, define the event handlers for the column to navigate to another page should a link attribute be supplied for a particular dataset. In the code below, the first thing you'll see is how to duplicate the column for all the dataset:

var dupLevel;for (i=1; i<=chartParams.num; i++) {	//Render the x-axis label	createText(_global.data[i].setName, _global.data[i].setXPos, (_global.data[i].setYPos) +((_global.data[i].setValue/Math.abs(_global.data[i].setValue))*chartParams.fontSize), _global.chartParams.font, _global.chartParams.fontSize, _global.chartParams.fontColor, false, "center", getLevel());	//Now, render the column	//To render the column - just duplicate MovColumn and pass the parameteres	dupLevel = getLevel();	duplicateMovieClip("MovColumn", "ASMovColumn_"+dupLevel, dupLevel);	//Get a reference to the newly created column	mcColumn = _root["ASMovColumn_"+dupLevel];	//Set its x and y position and width	mcColumn._x = _global.data[i].setXPos;	mcColumn._y = _global.data[i].setYPos;	mcColumn._width = _global.data[i].setWidth;	//Convey the parameters to the column now.	//Whether to animate or not	mcColumn.fcAnimation = chartParams.animateChart;	//Required height	mcColumn.fcHeight = _global.data[i].setHeight;	//Color	mcColumn.fcColor = _global.data[i].setColor;	//Data index	mcColumn.dataIndex = i;The next step is to define the link event handler for this column.//We also set the link handler - if a link has been specified	if (_global.data[i].setLink != "" && _global.data[i].setLink != undefined) {		mcColumn.onRelease = function() {			getURL(_global.data[this.dataIndex].setLink, "_self");		};	}}

The last step in the chart rendering process is to render the zero plane and re-render the canvas border (so that it overlaps the column base to give an aesthetic look):

//***** Draw the zero position line *****//drawLine(chartParams.CCanvasStartX, chartParams.zeroPlanePos, chartParams.CCanvasStartX+ chartParams.CCanvasWidth, chartParams.zeroPlanePos, chartParams.zeroPlaneThickness, chartParams.zeroPlaneColor, 100, getLevel());//***** Re-render the canvas border (overlay) *****//drawRectangle(getLevel(), chartParams.CCanvasStartX, chartParams.CCanvasStartY, chartParams.CCanvasStartX+chartParams.CCanvasWidth, chartParams.CCanvasStartY+ chartParams.CCanvasHeight, chartParams.canvasBrdrColor, chartParams.canvasBgColor, chartParams.canvasBrdrThickness, 100, 0);Finally you stop the play of the movie as the chart has been fully rendered.stop();

Listing 6 shows the entire chart rendering code.Exporting the Movie
Now that you're finished building the actual chart, you've want to make it Web-ready. Exporting the file converts your movie into a .swf file for use in Web pages. To do this, simply go to File?>Export Movie.

Implementation Methods
Now that your movie is Web-ready, you need to embed it into a HTML page, so people can see it! Use the following code:

... Other HTML Content ...... Other HTML Content ...

To correctly display a Flash movie in a browser, your HTML page should contain two specific tags: and . The tag is used by Internet Explorer and the tag is used by Netscape Navigator. Using only one tag may cause browser incompatibility, so always use both. Place the tag within the tag as shown in the example. ActiveX-enabled browsers will ignore the tag inside the tag. Netscape and old Microsoft browsers will not recognize the tag and will use only the tag to load the Macromedia Flash Player.

In the above code, the XML data required by the chart is missing. To include the XML data, use the FlashVars property, which you can find in the complete code for embedding the Flash Column Chart (Listing 7).

Charting with Dynamic Data
This involves using the Flash Column Chart with data pulled from a database. This example uses Microsoft Access as the database and ASP as the server-side script, however, any database and any scripting language will do as long as you're able to output proper XML.

The application you'll be creating will show the outputs of various factories of a company on a single chart distributed on the date factor. The user will select a factory from the list of factories as well as a date range, and receive a chart of the work done in that factory.


Figure 5. FactoryDB.mdb: Here's the structure for the database.
 
Figure 6. It works! This shows FactoryDB.mdb in working mode after it's been fed dummy data.

The Database
The database for this example is named FactoryDB.mdb. It's a very simple database with just two tables:

  • Factory_Master: the master table that contains an entry for each factory, represented by an Id and its name.
  • Factory_Output: the main data table (with a FK to Factory_Master on the field Id) that contains two other fields, the date and the number of output units for that particular date.

Figure 5 shows the database structure. Figure 6 shows the database in working mode after it's been fed dummy data.

The Front-end of the Application
You've got a way to access your data, now you need a way to present it. This application uses ASP pages to create an interface for your DB app:

  • DBConn.asp: Data Connection String container
  • Colors.asp: Contains a single dimension array named Colors. Each row in the array contains the hexadecimal code for a color (without the #). Use this array later to get different colors for different data sets.
  • ColorPicker.asp: Consists of a DHTML color selector.
  • Default.asp: The form where the user picks the factory whose data he wishes to see.
  • Chart.asp: Requests the data submitted to it (by Default.asp), processes it, interacts with the DB, and finally renders the Flash Column Chart.

Default.asp is a simple database driven form that aids the user in selecting the factory and date apart from a few chart visual properties. Figure 7 shows the interface.

Figure 7. Default.asp: This form provides the interface for the database.

When you click on the "Chart It!" button, you'll be taken to Chart.asp.

First, include the header files DBConn.asp and Colors.asp and render the and render the part:

<%@ Language=VBScript %>                Factory Output Report - Chart                

Next, the data submitted at Default.asp is requested:

<%         'We first request the values from the previous page        Dim oRs, strQuery         Dim fromDate, toDate        Dim factoryId, bgColor, canvasBgColor, canvasBrdrColor         'strXML will be used to store the entire XML document generated        Dim strXML, intCounter, dateDiffer        intCounter = 0        factoryId = Request.Form("sFactory")        fromDate = Request.Form("fromDate")        toDate = Request.Form("toDate")         bgColor = Request.Form("bgColor")        canvasBgColor = Request.Form("canvasBgColor")        canvasBrdrColor = Request.Form("canvasBrdrColor")

Then, the database is queried and the XML is generated for the required date range:

'Initialize the RecordSet        Set oRs = Server.CreateObject("ADODB.Recordset")        'Generate the chart element string        strXML = ""        'get the difference between the two dates        dateDiffer = DateDiff("d", fromDate, toDate)         'Get the data for the selected factory        strQuery = "select * from Factory_Output where FactoryId=" & factoryId & " and DatePro>=#" _& fromDate & "# and DatePro<=#" &         dateAdd("d",1,toDate) & "#"        Set oRs = oConn.Execute(strQuery)        'Generate the  tags now        While Not oRs.Eof        'Increase the counter        intCounter = intCounter + 1        strXML = strXML & ""         oRs.MoveNext        Wend         strXML = strXML & ""        Set oRs = nothing%>

Finally, the HTML code to render the chart is written out:

  

When you view the chart, it should look something like Figure 8

Figure 8. The final product! Here's a look at the completed Flash Colum Chart.

Encore!
Now that you have your own Flash Chart, you don't need to rely on third-party solutions! The looks of this chart can easily be customized to suit your own and your audience's needs. Also, unlike static graphs, the animated graph makes viewing a pleasure. The small size of the graph makes it very suitable for narrow bandwidth connections. Also, the conversion of data to XML (which the chart needs) is very easy to do. A single page with the graph embedded in it can handle all the graphs for your site. An implementation of complete separation of data from presentation, this graph can work even in static servers, where .xml files are statically stored and are changed within a certain period. Also, this graph is compatible across a large number of platforms namely, ASP, ASP.NET, PHP, CGI, etc. This is but a mere glimpse into what you can accomplish with Flash.

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Overview

The Latest

your company's audio

4 Areas of Your Company Where Your Audio Really Matters

Your company probably relies on audio more than you realize. Whether you’re creating a spoken text message to a colleague or giving a speech, you want your audio to shine. Otherwise, you could cause avoidable friction points and potentially hurt your brand reputation. For example, let’s say you create a

chrome os developer mode

How to Turn on Chrome OS Developer Mode

Google’s Chrome OS is a popular operating system that is widely used on Chromebooks and other devices. While it is designed to be simple and user-friendly, there are times when users may want to access additional features and functionality. One way to do this is by turning on Chrome OS

homes in the real estate industry

Exploring the Latest Tech Trends Impacting the Real Estate Industry

The real estate industry is changing thanks to the newest technological advancements. These new developments — from blockchain and AI to virtual reality and 3D printing — are poised to change how we buy and sell homes. Real estate brokers, buyers, sellers, wholesale real estate professionals, fix and flippers, and beyond may

©2023 Copyright DevX - All Rights Reserved. Registration or use of this site constitutes acceptance of our Terms of Service and Privacy Policy.

Sitemap