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.
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.
The following are the steps required to build a comparison bar chart:
ComparisonChartData
. Check the file out; it is basically a label and a vector of BarData
from the previous project.VerticalAxis.as
, HorizontalAxis.as
, and Bar.as
, 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.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);
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); } }
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 find 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.
We added complexity to the BarChart
code and created the ComparisonBarChart
. In the following section we will look at how to improve it.
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.
Definitely have a look at the recipe Building vertical bar charts in this chapter, creating bar charts from which this one was made. Also, you can easily tweak the recipe Drawing a bar chart in Flex in the chapter, creating bar charts to replicate what was shown in this recipe but using Flex.
3.128.173.53