Creating Bar Charts

(For more resources related to this topic, see here.)

Drawing a bar chart with Flex

The Flex framework offers some charting components that are fairly easy to use. It is not ActionScript per say, but it still compiles to the SWF format. Because the resulting charts look good and are pretty customizable, we decided to cover it in one recipe. There is a downside though to using this: the Flex framework will be included in your SWF, which will increase its size. Future recipes will explain how to do the same thing using just ActionScript.

Getting ready

Open FlashDevelop and create a new Flex Project.

How to do it...

The following are the steps required to build a bar chart using the Flex framework.

Copy and paste the following code in the Main.mxml file. When you run it, it will show you a bar chart.

<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="" xmlns:s="library://" xmlns:mx="library://" minWidth="955" minHeight="600"> <fx:Script> <![CDATA[ import mx.collections.ArrayCollection; [Bindable] private var monthsAmount:ArrayCollection = new ArrayCollection( [ { Month: "January", Amount: 35}, { Month: "February", Amount: 32 }, { Month: "March", Amount: 27 } ]); ]]> </fx:Script> <mx:BarChart id="barchart" x="30" y="30" dataProvider="{monthsAmount}"> <mx:verticalAxis> <mx:CategoryAxis categoryField="Month"/> </mx:verticalAxis> <mx:horizontalAxis> <mx:LinearAxis minimum="10"/> </mx:horizontalAxis> <mx:series> <mx:BarSeries yField="Month" xField="Amount" /> </mx:series> </mx:BarChart> </s:Application>

How it works...

When you create a new Flex project, Flash Builder will generate for you the XML file and the Application tag. After that, in the script tag we created the data we will need to show in the chart. We do so by creating an ArrayCollection data structure, which is an array encapsulated to be used as DataProvider for multiple components of the Flex framework, in this case mx:BarChart.

Once we have the data part done, we can start creating the chart. Everything is done in the BarChart tag. Inside that tag you can see we linked it with ArrayCollection, which we previously created using this code: dataProvider = "{monthsAmount}".

Inside the BarChart tag we added the verticalAxis tag. This tag is used to associate values in the ArrayCollection to an axis. In this case we say that the values of the month will be displayed on the vertical axis.

Next comes the horizontalAxis tag, we added it to tell the chart to use 10 as a minimum value for the horizontal axis. It's optional, but if you were to remove the tag it would use the smallest value in ArrayCollection as the minimum for the axis, so one month, in this case, March, would have no bar and the bar chart wouldn't look as good.

Finally, the series tag will tell for a column, what data to use in ArrayCollection. You can basically think of the series as representing the bars in the chart.

There's more...

As we mentioned earlier, this component of the Flex framework is pretty customizable and you can use it to display multiple kinds of bar charts.

Showing data tips

Multiple options are available using this component; if you want to display the numbers that the bar represents in the chart while the user moves the mouse over the bar, simply add showDataTips = "true" inside the BarChart tag and it is done.

Displaying vertical bars

If you would like to use vertical bars instead of horizontal bars in the graph, Flex provides the ColumnChart charts to do so. In the previous code, change the BarChart tag to ColumnChart, and change BarSeries to ColumnSeries. Also, since the vertical axis and horizontal axis will be inverted, you will need verticalAxis by horizontalAxis and horizontalAxis by verticalAxis (switch them, but keep their internal tags) and in the ColumnSeries tag, xField should be Month and yField should be Amount. When you run that code it will show vertical bars.

Adding more bars

By adding more data in the ArrayCollection data structure and by adding another BarSeries tag, you can display multiple bars for each month. See the Adobe documentation at the following link to learn how to do it:

Building vertical bar charts

Now that we have built a bar chart using Flex, we are ready to do the same in pure ActionScript. This bar chart version will allow you to expand it in multiple ways and will remove the weight that the Flex framework adds to the file size. Now a bit about bar charts; Bar charts are good when you don't have too much data (more than 20 bars starts to make a big chart), or when you've averaged it. It is a quick way to compare data visually.

Getting ready

All we will need for this is to start a new project in FlashDevelop. Also, it would help to read about preparing data and about axes in the book ActionScript Graphing Cookbook.

How to do it...

This section will refer a lot to the code provided with the book. You will notice that we divided all the elements in the charts into their own classes.

  1. It all starts in the file, where we create the data that we will use to display in the chart after that we just create the chart and add it to the display list.

    var data:Vector.<BarData> = new Vector.<BarData>(); data.push(new BarData("January", 60)); data.push(new BarData("February", 100)); data.push(new BarData("March", 30)); var chart:BarChart = new BarChart(data, 400, 410); chart.x = 30; chart.y = 30; addChild(chart);

  2. From here you can look into the BarData class, which it is just two variables, a string and a number that represents the data that we are going to show.

  3. We now need to create a class for all the elements that comprise a bar chart. They are: the bars, the vertical axis, and the horizontal axis. Now this recipe is building a vertical bar chart so the vertical axis is the one that will have numerical marks and the horizontal axis will have labels on the marks.

  4. First the Bar class: This class will only draw a rectangle with the height representing the data for a certain label. The following is its constructor:

    public function Bar(width:int, height:int) { graphics.beginFill(0xfca25a); graphics.drawRect(-width/2, 0, width, -height); graphics.endFill(); }

  5. The horizontal axis will take the x coordinate of the created bars and will place a label under it.

    public function HorizontalAxis(listOfMark:Vector.<Number>, data:Vector.<BarData>, width:Number) { drawAxisLine(new Point(0, 0), new Point(width, 0)); for (var i:int = 0; i < listOfMark.length; i++) { drawAxisLine(new Point(listOfMark[i], -3), new Point(listOfMark[i], 3)); var textField:TextField = new TextField(); textField.text = data[i].label; textField.width = textField.textWidth + 5; textField.height = textField.textHeight + 3; textField.x = listOfMark[i] - textField.width / 2; textField.y = 5; addChild(textField); } }

  6. Now the vertical axis will make 10 marks at regular interval and will add a label with the associated value in it:

    for (var i:int = 0; i < _numberOfMarks; i++) { drawAxisLine(new Point( -3, (i + 1) * -heightOfAxis / _ numberOfMarks ), new Point(3, (i + 1) * -heightOfAxis / _ numberOfMarks)); var textField:TextField = new TextField(); textField.text = String(((i + 1) / (_numberOfMarks)) * maximumValue ); textField.width = textField.textWidth + 5; textField.height = textField.textHeight + 3; textField.x = -textField.width - 3; textField.y = (i + 1) * -heightOfAxis / _numberOfMarks - textField.height / 2; addChild(textField); }

  7. Finally, the BarChart class will take the three classes we just created and put it all together. By iterating through all the data, it will find the maximum value, so that we know what range of values to put on the vertical axis.

    var i:int; var maximumValue:Number = data[0].data; for (i = 1; i < data.length; i++) { if (data[i].data > maximumValue) { maximumValue = data[i].data; } }

  8. After that we create each bar, notice that we also keep the position of each bar to give it to the horizontal axis thereafter:

    var listOfMarks:Vector.<Number> = new Vector.<Number>(); var bar:Bar; for (i = 0; i < data.length; i++) { bar = new Bar(_barWidth, data[i].data * scaleHeight); bar.x = MARGIN + _barSpacing + _barWidth / 2 + i * (_barWidth + _barSpacing); listOfMarks.push(bar.x - MARGIN); bar.y = height - MARGIN; addChild(bar); }

  9. Now all we have left to do is create the axes and then we are done; this is done really easily as shown in the following code:

    _horizontalAxis = new HorizontalAxis(listOfMarks, data, width - MARGIN); _horizontalAxis.x = MARGIN; _horizontalAxis.y = height - MARGIN; addChild(_horizontalAxis); _verticalAxis = new VerticalAxis(height - MARGIN, maximumValue); _verticalAxis.x = MARGIN; _verticalAxis.y = height -MARGIN; addChild(_verticalAxis);

How it works...

So we divided all the elements into their own classes because this will permit us to extend and modify them more easily in the future.

So let's begin where it all starts, the data. Well, our BarChart class accepts a vector of BarData as an argument. We did this so that you could add as many bars as you want and the chart would still work. Be aware that if you add many bars, you might have to give more width to the chart so that it can accommodate them.

You can see in the code, that the width of the bar of determined by the width of the graph divided by the number bars. We decided that 85 percent of that value would be given to the bars and 15 percent would be given to the space between the bars. Those values are arbitrary and you can play with them to give different styles to the chart.

Also the other important step is to determine what our data range is. We do so by finding what the maximum value is. For simplicity, we assume that the values will start at 0, but the validity of a chart is always relative to the data, so if there are negative values it wouldn't work, but you could always fix this. So when we found our maximum value, we can decide for a scale for the rest of the values. You can use the following formula for it:

var scaleHeight:Number = (height - 10) / maximumValue;

Here, height is the height of the chart and 10 is just a margin we leave to the graph to place the labels. After that, if we multiply that scale by the value of the data, it will give us the height of each bar and there you have it, a completed bar chart.

There's more...

We created a very simple version of a bar chart but there are numerous things we could do to improve it. Styling, interactivity, and the possibility of accommodating a wider range of data are just some examples.


This basic chart could use a little bit of styling. By modifying the color of the bars, the font of the labels, and by adding a drop shadow to the bars, it could be greatly enhanced. You could also make all of them dynamic so that you could specify them when you create a new chart.


It would be really good to show the values for the bars when you move the mouse over them. Right now you can kind of get an idea of which one is the biggest bar but that is all. If this feature is implemented, you can get the exact value.

Accommodating a wider data range

As we explained earlier, we didn't account for all the data range. Values could be very different; some could be negative, some could be very small (between 0 and 1), or you would want to set the minimum and maximum value of the vertical axes. The good thing here is that you can modify the code to better fit your data.

Creating comparison bar charts

In the previous recipe, we learned how to make a simple bar chart. The relation of the data was one-to-one; one label, one value. Now we will make this a bit more complex by adding one more dimension. We will create a bar chart in which the bars are replaced by bar charts. It can be hard to understand it like this, but it gets clearer if you look at the data. For this recipe we will compare the medals (bronze, silver, and gold) won by three different countries at a sporting event.

Getting ready

A good starting point is to copy over the project from the previous recipe (see the Building vertical bar charts recipe). We will modify it a lot, but the core of it will be similar.

How to do it...

The following are the steps required to build a comparison bar chart:

  1. As usual, when we create a new chart, we always start with the data. So we create a new class for it called ComparisonChartData. Check the file out; it is basically a label and a vector of BarData from the previous project.

  2. After that, in the main class we will generate the data. This example will use the number of medals won for countries as data. After that we create another chart.

  3. Now if you look at the classes,, and, you will notice that they have been only slightly modified. The HorizontalAxis class has been made a bit more data agnostic and requires a list of labels instead of being passed the data, that way we will be able to use the same class for bar chart and the comparison bar chart. The Bar class is now passed a color so that we can specify the color of the bar.

  4. Most of the changes happen in the ComparisonBarChart class. First we must determine the size of the bars:

    _categoryWidth = (chartWidth - MARGIN) * (1 - CATEGORY_PERCENT) / data.length; _categorySpacing = (chartWidth - MARGIN) * CATEGORY_PERCENT / (data.length + 1); _barWidth = _categoryWidth * (1 - BAR_PERCENT) / data[0].bars. length; _barSpacing = _categoryWidth * BAR_PERCENT / (data[0].bars.length – 1);

  5. After that we loop over the data and create all the bars:

    for (i = 0; i < data.length; i++) { var markX:Number = _categorySpacing + _categoryWidth / 2 + i * (_categoryWidth + _categorySpacing); listOfMarks.push(markX); listOfLabels.push (data[i].label); for (j = 0; j < data[i].bars.length; j++) { bar = new Bar(_barWidth, data[i].bars[j].data * scaleHeight, data[i].bars[j].color); bar.x = MARGIN + markX - _categoryWidth / 2 + j * (_barWidth + _barSpacing) + _barWidth / 2; bar.y = chartHeigth - MARGIN; addChild(bar); } }

How it works...

As we mentioned in the Introduction, we added a dimension to the chart so the data must reflect it. In this case we reuse the BarData class we had in the previous class, which is still very relevant (our chart will still have bars) but we create another class (ComparisonChartData) to hold a list of BarData.

After that the only hard part is determining the space allowed for each category (in this example: each country). We use the same formula as for determining the size of the bars in the BarChart recipe. Each category will be subdivided into multiple bars. So from the category width we can now fnd the width of the bars. We also took the liberty of assigning 15 percent for the space between the bars.

Finally we loop over all the data. Since our data is more complex now, we must do a loop inside of another loop to create all the bars. We find the position of the marks inside the first loop much like we found the position of the bars in the BarChart class. And from that position, we find the position of each of the bars for each of the categories.

There's more...

We added complexity to the BarChart code and created the ComparisonBarChart. In the following section we will look at how to improve it.

Adding a legend

Not having a legend for the previous chart was fine because you could have understood what it was depicting just by looking at it. But in the case of more complex data, a legend could really help explaining what we are trying to show with the chart. Fortunately, creating a legend is really easy. You should create a class for it, which you could re-use in other charts or graph.

Drawing histograms

Well truth be told, we won't really be making histograms with this recipe but mostly bar charts in the style of histograms. Histograms are very rigid in their nature and follow really specific mathematical functions to represent frequency and density. You can read more on histograms on Wikipedia: What we are going to do here is build a histogram styled bar chart (no space between the bars) that uses a function as input. You can think of this as a different way to do an area chart or a line chart.

Getting ready

The data for this recipe is a bit different as it uses a mathematical function instead of a data set. You can get a mathematical function using interpolation or by having a program such as Microsoft Excel do it for you.

How to do it...

The following are the steps required to build a histogram using ActionScript 3:

  1. Now if you look at our class, you will notice that it is quite small compared to the previous recipe. For this recipe, we don't need to create data; we will use a function to get our data. The function used in this case is the one as follows:

    public function dataFormula(xValue:Number):Number { return (xValue * xValue * xValue); }

  2. Once we have this function we can create the chart:

    var chart:Histogram = new Histogram(dataFormula, 400, 410, 25);

  3. Next, in the file we will add a style to the line because the bars will be really close in this chart and this will help differentiate them.

  4. Finally, the file is different than and takes a function as a parameter in the constructor. From that function, we will determine the maximum value and we will create the bars.

    var maximumValue:Number = data(0); for (i = 1; i < numberOfBars; i++) { if (data(i) > maximumValue) { maximumValue = data(i); } } var scaleHeight:Number = (chartHeight - 10) / maximumValue; var listOfMarks:Vector.<Number> = new Vector.<Number>(); var listOfLabels:Vector.<String> = new Vector.<String>(); var bar:Bar; for (i = 0; i < numberOfBars; i++) { bar = new Bar(_barWidth, data(i) * scaleHeight); bar.x = 10 + _barWidth / 2 + i * (_barWidth); listOfMarks.push(bar.x - 10); listOfLabels.push(String(i)); bar.y = chartHeight - 10; addChild(bar); }

How it works...

Contrary to the other recipe, this one won't use a list of numbers as data but a function in the code called dataFunction. This example will use the function y = x3. The value on the vertical axis is equal to the value on the horizontal axis multiplied by itself two times (to the power of three). But you could use any function that takes a number and returns one.

Since we want the graph to be in the style of a true histogram, we don't need to compute any space between the bars. To get the width of the bars, we take the width of the graph divided by the number of bars plus one. We add one to the number of bars so that the last bar doesn't come too close to the end of the graph on the right-hand side.

We are now ready to use our function to get our data. Since we know it takes a number and returns a number, by giving it our value of the horizontal axis it will return the value of the vertical axis. The only code we have to write to do so is data (horizontalAxisValue). In our case that value is the index of our loop. Note that we could have modifed the HorizontalAxis class to be like the VerticalAxis class, but it still worked (the labels weren't too big) so we left it as it is.

There's more...

Accepting a wider data range would improve the Histogram class, but also, you could use it in a different way by making it draw a lot of bars.

Data range

Here again the data range is very important. It would be good to modify the code for this recipe so that it could accept a minimum value and a step value. In this example, our minimum was 0 and our step value was 1. But that may not fit for every function or data.

So many bars

One interesting thing to note here is that if you set the number of bars to be very high, you will end up creating an area chart since the bars will be really thin. If you want to use this chart in this way, I would suggest modifying the HorizontalAxis class because we used it as it is from the BarChart recipe and it would create way too many labels.

Creating sparklines to enrich text content

Sparklines are small line charts that are used to augment the value of some other content by giving a visual trend of a specific metric. One of the easy examples of applications that use sparklines is Google Analytics.

As you can see in the previous screenshot, the sparklines on the left give you a clearer background about the numbers on the right. So as of today, you had 13,935 visits but those varied in a specifc pattern in the previous month.

Getting ready

Just start a new project in FlashDevelop. This will be a really simple recipe.

How to do it...

The following are the steps required to build sparklines:

  1. Since sparklines are a pretty simple graph, we only have two classes for this recipe. In the main class, we generate the data and instantiate the Sparkline class. All of the drawing is done inside

  2. We will only use the graphics function of the Sprite class to draw the line and the axes:

    graphics.lineStyle(1, 0x0000ff); graphics.moveTo(0, chartHeight-data[0] * scaleHeight); for (i = 1; i < data.length; i++) { graphics.lineTo(i * _stepSize, chartHeight-data[i] * scaleHeight); } graphics.lineStyle (1, 0); graphics.moveTo(0, chartHeight); graphics.lineTo(0, 0); graphics.moveTo(0, chartHeight); graphics.lineTo(chartWidth, chartHeight);

How it works...

Using the Flash Drawing API, the previous code will draw the two axes and draw a line that will represent our data.

We based the data on visits to a website for a day. We randomly assigned values ranging from 9000 to 15500. This graph will give us an idea of how the traffic varied during the previous month.

The thing to notice here is that since this line graph is so small, there are no labels anywhere. The goal here is not to check a precise data point, but more to derive a trend from the graph.

We still need, like in the other graph, to determine the highest value in the data set to convert values to pixels. In this case, since we didn't provide x and y coordinates, we use the index of the vector as the horizontal coordinate; that is why we need to find the stepSize value. After that, we can just iterate over the data and draw a succession by using the lineTo calls.

for (i = 1; i < data.length; i++) { graphics.lineTo(i * _stepSize, chartHeight-data[i] * scaleHeight); }

From there the job is mostly done; we only need to draw the axes. This is done easily by the lineTo calls since we don't need to add labels.

There's more...

By coloring the area under the line and averaging the data we could improve on the sparkline recipe.

Adding the area under the line

The graphs from Google Analytics also have the area under the line drawn, so if we wanted to replicate that it wouldn't be too hard. We would have to make a second for loop before the one we already have and add a beginFill call before it. After that we have to make sure we close the shape so that the fill is complete. We draw the fill before so that is doesn't hide the line. You could also do it all in one loop if you started lineStyle just before drawing the top side of the area and if you remove it just after.

Averaging the data

As you can see, the line is a bit jerky in the graph. Since we are more interested in the trend with sparklines, you could average the data for every two or three values. This would give you fewer data points and you would lose some precision, but it would, in return, give you a smoother line and it might be easier to see the trends.

Making 3D bar charts

In the recipe Building vertical bar charts in this article, we showed how to make a simple bar chart in ActionScript. For this recipe, we wanted to spice it up a bit and make it 3D.

How to do it...

The following steps will show you how to convert a 2D bar chart to 3D:

  1. Take,,, and from the Building vertical bar charts recipe from the code files provide with the book; these files are not going to change.

  2. Now in, increase the space between the bars. These are the lines that change:

    _barWidth = (width - 10) * 70 / 100 / data.length; _barSpacing = (width - 10) * 30 / 100 / (data.length + 1);

  3. The big changes will be in the file. First we will add two helper functions to go back and forth between the color model, as shown in the following code snippet:

    private function _hexToRGB(hex:uint):Object { var rgbObj:Object = { red: ((hex & 0xFF0000) >> 16), green: ((hex & 0x00FF00) >> 8), blue: ((hex & 0x0000FF)) }; return rgbObj; } private function _RGBtoHEX(red:int, green:int, blue:int):uint { return red << 16 | green << 8 | blue; }

  4. We will need to compute a new color for the top and right part. The following code will show us how we get the color for the top part:

    var baseColor:Object = _hexToRGB(color); += * 0.1; if ( > 255) { = 255; } += * 0.1; if ( > 255) { = 255; } += * 0.1; if ( > 255) { = 255; } var topColor:uint = _RGBtoHEX(,,;

  5. All that is left to do, is draw two parallelograms that will make our bar look 3D:

    graphics.beginFill(topColor); graphics.moveTo(-width / 2, -height); graphics.lineTo(-width / 2 + xOffset, -height - yOffset); graphics.lineTo(width / 2 + xOffset, -height - yOffset); graphics.lineTo(width / 2, - height); graphics.lineTo( -width / 2, -height); graphics.beginFill(rightColor); graphics.moveTo(width / 2, 0); graphics.lineTo(width / 2 + xOffset, 0 - yOffset); graphics.lineTo(width / 2 + xOffset, -height - yOffset); graphics.lineTo(width / 2, - height); graphics.lineTo(width / 2, 0);

How it works...

We are basically taking every class from the Building vertical bar charts recipe, unchanged, except for and

In, we made a small modification to leave more space between our bars. Indeed, we will need space to have our 3D representing shapes. Before, we had 15 percent of space between bars; we will up that to 30 percent (in step 2).

The meaty part is in We will add two parallelograms to simulate the 3D effect, one for the top and the other for the side to give a sense of depth. Those are pretty simple to draw; we find the x and y of the off-setted top part of our parallelogram (once you have this point you can use it to find all the other points of the shape) and using the lineTo function, we can draw lines until we are back to the starting position (that is, step 6).

That already gives us a 3D looking shape, but there is a small problem. Since every piece is the same color, it reduces the 3D effect. That is why we are going to change the color of the top and right parallelograms. The top one is going to be of a lighter color and the right part is going to be of a darker color than the color specified in the parameters.

To compute those colors, we will need to decompose the hex colors provided into red, green, and blue. For each of those components, we are going to add or remove 10 percent of their value (add for lighter, remove for darker) thus keeping a similar color. That is exactly what we do in step 5.

Finally we convert it back to hexadecimal, as it is the format that the beginFill function expects.

Now our 3D bar chart looks great!

There's more...

By using gradients and a real 3D engine you could improve on this recipe.

Using gradient

Another option to using different color tones and to accentuate the 3D effect, would be to use a gradient on the top and right parts. It would make your bar chart look a bit more refined.

Using a real 3D engine

Here we faked the 3D, but to get really good results that are easier to animate or to interact with, you should use a real 3D engine such as Away3D, which you can find here:


This article gave us all the tools to create multiple bar charts, be it vertical, horizontal, comparison, or histograms, it provided us with solid bases to improve those charts even more.

Resources for Article :

Further resources on this subject:

You've been reading an excerpt of:

ActionScript Graphing Cookbook

Explore Title