Building pyramid charts

Pyramid charts are very similar to pie charts and can be mostly used for the same purpose. But there is one more piece of information that can be given by using pyramid charts, a sense of hierarchy. The pyramid has a top and bottom layer and there are layers in between too, usually the top layer being the most important.

Building pyramid charts

Getting ready

Look at the project files in the code folder. Also, having a good grasp on the Pythagorean theorem, available at http://en.wikipedia.org/wiki/Pythagorean_theorem, is important.

How to do it...

The following are the steps required to create a pyramid chart:

  1. First we will create the data structure to represent a layer in our pyramid chart. The following is PyramidData.as:
    public class PyramidData {
       public var startingPercent:Number;
        public var endingPercent:Number;
        public var label:String;
        public var color:uint;
        public var labelOustideOfChart:Boolean;
    
        public function PyramidData(newStartingPercent:Number, newEndingPercent:Number, newLabel:String, newColor:uint, newLabelOutsideOfChart:Boolean = false ) {
        startingPercent = newStartingPercent;
          endingPercent = newEndingPercent;
          label = newLabel;
          color = newColor;
          labelOustideOfChart = newLabelOutsideOfChart;
        }
      }
  2. After that we can create the PyramidChart.as file. It uses the Flash graphics API to draw each layer.
    var lenghtOfTop:Number = data[i].startingPercent * graphWidth * Math.sin(30 * Math.PI / 180);
    var lenghtOfBottom:Number = data[i].endingPercent * graphWidth * Math.sin(30 * Math.PI / 180);
    
    point1 = new Point (graphWidth / 2 - lenghtOfTop, data[i].startingPercent * graphHeight);
    point2 = new Point (graphWidth / 2 - lenghtOfBottom, data[i].endingPercent * graphHeight);
    point3 = new Point (graphWidth / 2 + lenghtOfBottom, data[i].endingPercent * graphHeight);
    point4 = new Point (graphWidth / 2 + lenghtOfTop, data[i].startingPercent * graphHeight);
    
    graphics.beginFill(data[i].color);
    graphics.lineStyle(1, 0);
    graphics.moveTo(Math.round(point1.x), Math.round(point1.y));
    graphics.lineTo(Math.round(point2.x), Math.round(point2.y));
    graphics.lineTo(Math.round(point3.x), Math.round(point3.y));
    graphics.lineTo(Math.round(point4.x), Math.round(point4.y));
    graphics.lineTo(Math.round(point1.x), Math.round(point1.y));
  3. Finally in Main.as we generate the data and we create the pyramid chart.

How it works...

As you can see our data here is a bit more complicated. It has five properties to represent a layer in the pyramid chart. The most important properties are startingPercent and endingPercent. These will tell you where to start and end a layer. It is a value between 0 and 1; 0 being the top of the pyramid and 1 being the bottom. As you can see in the example, the values don't have to be continuous for it to work. Having a gap in between layers gives it a different style. The caveat to this is that if layers overlap it won't look as good.

The PyramidChart.as class refers to a bit of math to draw every piece of the graph. We decided to draw an equilateral triangle (where the three sides of the triangle are of the same length) for our pyramid because it is more pleasing to the eyes, but we could also have used an isosceles triangle (where two sides of the triangle are of the same length). Each side of the triangle will be the equal to the width of the graph. Once we know this we can figure out the height of the triangle by using the Pythagorean theorem.

graphHeight = Math.sqrt(graphWidth * graphWidth - (graphWidth / 2 * graphWidth / 2));

From there we need to draw each layer based on the data given. Each layer will be a trapezoid and we will need to find the coordinates of each of its four corners. These corners are located along the sides of our equilateral triangle. So by using the startingPercent and endingPercent properties and a bit of trigonometry, we will end up with our points. The following code snippet shows how we can find our first point:

var lenghtOfTop:Number = data[i].startingPercent * graphWidth * Math.sin(30 * Math.PI / 180);
point1 = new Point (graphWidth / 2 - lenghtOfTop, data[i].startingPercent * graphHeight);

You can see in the Math.sin function that we use 30 degrees as an angle. Since we have an equilateral triangle, all the angles in it are 60 degrees. Our calculations use half of the triangle to get a right triangle; the top angle will be half of 60 degrees and therefore, 30 degrees. The sine formula uses radians and not degrees so we must convert it; that's why we multiply it by PI and divide it by 180 degrees.

Once we have our four points, it is just a matter of using the Flash drawing API and tracing lines between them.

The last part is to add the labels. Now we can either put the labels inside the graph or outside, but sometimes the labels will be too wide and won't fit inside the graph so there will be no choice but to put them outside. We added a Boolean value in the PyramidData class so that we can indicate where we want the labels to be.

If the label is outside the graph, it should start at the same x coordinate as the bottom-right corner of its layer (that is, the trapezoid). If it is inside the layer, its width should be the smallest width (the top part) of the layer. That way we can be sure that the labels will never intersect with the sides of the graph.

There's more...

Users should consider using getters and setters, and 3D to make this chart better.

Getters and setters

In this recipe and the previous ones, we used public variables in our data for the sake of simplicity. But in this case the startingPercent and endingPercent property values must be between 0 and 1, so it might be good to check for that and give an error message if they are not. This would make the code sturdier.

3D!

Pyramid charts are good, but this recipe uses a triangle as the base shape of the chart. Now by going with a real 3D pyramid, it would make it look even better. There's no need to use a 3D engine. Just emulating it with the graphics API would be enough to enhance the look.

See also

  • The Drawing a pie chart with Flex recipe
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.141.6