Creating donut charts

Very similar to pie charts, donut charts allow you to vary the visual if you have been using pie charts a lot. And since we used Flex to build the pie chart in the previous recipe, we thought it would be good to show how to build a pie chart/donut chart using pure ActionScript 3.

Creating donut charts

Getting ready

This recipe bases some of its code on the wedge class by Adobe's evangelist Lee Brimelow; you can check it here: http://www.leebrimelow.com/?p=430. Apart from that you can look up the code you will get from http://www.packtpub.com.

How to do it...

The following are the steps required to build a donut chart:

  1. We will start by creating the data class in this case DonutChartData.as.
    public var color : uint;
    public var percent : Number;
    public function DonutChartData(newPercent:Number, newColor:uint){
      percent = newPercent;
      color = newColor;
    
    }
  2. From there we will create the visual building block of this chart: DonutChartWedge.as. This class could also be used in a pie chart. The following is the part where we draw the wedge using the Flash drawing API:
     startPointX = Math.cos(angle) * radius;
     startPointY = Math.sin(-angle) * radius;
    
    graphics.lineTo(startPointX, startPointY);
    
    for (var i:int=0; i < numOfSegs; i++) {
      angle += segAngle;
      angleMid = angle - (segAngle / 2);
      midPoint = radius / Math.cos(segAngle / 2);
      anchorX = Math.cos(angle) * radius;
      anchorY = Math.sin(angle) * radius;
      controlX = Math.cos(angleMid) * midPoint;
      controlY = Math.sin(angleMid) * midPoint;
      graphics.curveTo(controlX, controlY, anchorX, anchorY);
    }
    // Close the wedge
    graphics.lineTo(0, 0);
    graphics.endFill();
  3. Next, we create the mask in the shape of a circle with a hole in the middle. It will transform a pie chart into a donut chart. This is done inside DonutChart.as.
    _donutMask.graphics.lineTo(outerRadius, 0);
    midPoint = outerRadius / Math.cos(segAngle / 2);
    for (i = 0; i < numOfSegs; i++) {
      angle += segAngle;
      angleMid = angle - (segAngle / 2);
      anchorPointX = outerRadius*Math.cos(angle);
      anchorPointY = outerRadius*Math.sin(angle);
      controlPointX = Math.cos(angleMid) * midPoint;
      controlPointY = Math.sin(angleMid) * midPoint;
      _donutMask.graphics.curveTo(controlPointX, controlPointY, anchorPointX, anchorPointY);
    }
    _donutMask.graphics.moveTo(0, 0);
    _donutMask.graphics.lineTo(innerRadius, 0);
    midPoint = innerRadius / Math.cos(segAngle / 2);
    for (i = numOfSegs; i > 0; i--) {
      angle -= segAngle;
      angleMid = angle + (segAngle / 2);
      anchorPointX = innerRadius * Math.cos(angle);
      anchorPointY = innerRadius * Math.sin(angle);
      controlPointX = Math.cos(angleMid) * midPoint;
      controlPointY = Math.sin(angleMid) * midPoint;
      _donutMask.graphics.curveTo(controlPointX, controlPointY, anchorPointX, anchorPointY);
    }
    addChild(_donutMask);
  4. Still inside DonutChart.as, from the data we will create all the wedges:
    var wedge:DonutChartWedge;
    _chartWedgeVector = new Vector.<DonutChartWedge>();
    if (data != null){
      for (i=0; i < data.length; i++){
        wedge = new DonutChartWedge(radius, data[i].percent * 360, data[i].color);
        _wedgeHolder.addChild(wedge);
        _chartWedgeVector.push(wedge);
          if (i != 0){
          wedge.rotation = _chartWedgeVector[i - 1].rotation + _chartWedgeVector[i - 1].arc;
        }
      }
    }

How it works...

The data for a donut chart is simple; it is a percentage (value between 0 and 1) and a color. Usually you would want all of your percentage to add up to one, but this implementation of the donut chart will work even if it doesn't.

As for the DonutChartWedge.as file, it is a slight modification to Lee Brimelow's Wegde code. In his version, you would pass it to Shape or Sprite and it would draw the wedge on it. We preferred to make the wedge itself a Sprite class as it could be used in the future to make the chart animated or interactive.

The code uses basic trigonometry to find points on the circle and draw a succession of arcs in order to simulate a bigger arc of a circle. You see, Flash graphics API uses quadratic Beziers in its curveTo function and because of this if we want to draw an arc of a circle we must do this in little chunks.

If we were to leave it like this, our class would be creating pie charts. The part that makes it a donut chart is the mask we create in DonutChart.as. To create the donut shape of the mask we draw two concentric circles filling the area between those circles. We do this in a very similar fashion as when we create the wedges. Note that a big part of the code is converting angles from degrees to radians in order to use trigonometry.

There's more...

We would need to add labels to make this chart more complete. Also, there is a little trick to use the DonutChart.as as a pie chart.

Labels

Labels would have added a large amount of code so we omitted them. But if you wanted to add them it wouldn't be too hard. You would basically make a switch statement and depending of the middle angle of a wedge, position and align the labels. You could also add the labels inside the wedges, but you have to make sure the chart is big enough.

Donut chart as a pie chart

If you wanted to use the DonutChart.as file as a pie chart , it would be possible to do so. The difference between the donut chart and the pie chart is that the donut chart has a mask on it hiding the middle part of the chart. If you made the mask show the full chart, then you would have a pie chart. To do so, make the strokeWidth property on donutChart equal to the radius property and there you have it, a pie chart.

See also

The donut chart fills similar needs as the pie chart so you could check out the previous recipe. Also, this recipe is using calls to the curveTo function to draw parts of circles, and the next recipe (drawing meters and gauges) will also use the curveTo functions.

..................Content has been hidden....................

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