Build a Better Charting Engine Using Flash and XML (cont'd)
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.
advertisement

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 Caption
createText(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 textbox
createText(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 textbox
createText(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.
Previous Page: Parsing the XML Data Next Page: Exporting the Movie


Page 1: IntroductionPage 5: Parsing the XML Data
Page 2: Lights! Camera! ActionScript!Page 6: Calculations for the Chart
Page 3: The Chart Scene's LayersPage 7: Exporting the Movie
Page 4: Loading the XML DataPage 8: The Front-end of the Application