Creating a pie chart

The steps to create a pie chart are relatively easy and short. Pie charts are ideal for showcasing a closed amount of data that we want to easily compare between data fields such as, in our example, dividing the number of people in the world into groups based on their region:

Creating a pie chart

Getting ready

The first step will be to update our canvas size in the HTML area to be a rectangular area. In our sample, we will update the values to 400 x 400. That's about it; let's start building it.

How to do it...

In the following steps we will create our first pie chart. Let's get started:

  1. Set up our data source and our global variables:
    var data= [	{label:"Asia", value:3518000000,style:"#B1DDF3"},
      {label:"Africa", value:839000000,style:"#FFDE89"},
      {label:"Europe", value:803000000,style:"#E3675C"},
      {label:"Latin America and Caribbean", value: 539000000,style:"#C2D985"},
      {label:"North America", value:320000000,style:"#eeeeee"},
      {label:"Near East", value:179000000,style:"#aaaaaa"},
      {label:"Oceania", value:32000000,style:"#444444"}
      ];
    var wid;
    var hei;
    var radius = 100;
  2. Prepare our canvas (from here on we are delving into the init function):
    function init(){
      var can = document.getElementById("bar");
    
      wid = can.width;
      hei = can.height;
      var context = can.getContext("2d");
    ...
  3. Count the total data (world population):
    var total=0;
    for(var i=0; i<data.length; i++) total+=data[i].value;
  4. Set up 360 degrees in radians and move our pivot point to 0,0:
    var rad360 = Math.PI*2;
    context.translate(wid/2,hei/2);
  5. Draw the pie chart by using the following code snippet:
    var currentTotal=0;
      for(i=0; i<data.length; i++){
      context.beginPath();
      context.moveTo(0,0);
      context.fillStyle = data[i].style;
      context.arc( 0,0,radius,currentTotal/total*rad360,(currentTotal+data[i].value)/total*rad360,false);
      context.lineTo(0,0);
      context.closePath();
      context.fill();	
    
      currentTotal+=data[i].value;
      }
    }

That's it; we have just created a basic pie chart—I told you it would be easy!

How it works...

Our pie chart, as its name indicates, uses pies and always showcases 100 percent of data. As our arc method works based on radians, we need to convert these data points from percentile to radians.

After figuring out what the total of all the values is and the total radians in a circle (2*PI), we are ready to loop through and draw the slices.

var currentTotal=0;
  for(i=0; i<data.length; i++){
    context.beginPath();
    context.moveTo(0,0);
    context.fillStyle = data[i].style;

The logic is relatively simple; we loop through all the data elements, change the fill style based on the data object, and move our pointer to 0,0 (to the center of our screen as we have changed the pivot point of our canvas).

context.arc( 0,0,radius,currentTotal/total*rad360,(currentTotal+data[i].value)/total*rad360,false);
context.lineTo(0,0);
context.closePath();
context.fill();	

currentTotal+=data[i].value;

Now we draw the arc. Pay attention to the highlighted text; we start with where we left off our current total and through that we calculate the angle in radians:

currentTotal/total*rad360

We can turn this value into a percentage value that we can duplicate against the total radian of our circle. Our second parameter is very close, so we just add into it the current value of the current region we are in:

(currentTotal+data[i].value)/total*rad360

And the last point to note here is that we are setting the arc's last parameter to false (counter clockwise) as that works best for our calculations.

Last but not least, we update our currentTotal value to encompass the newly added region as that will be our starting point in the next round of our for loop.

There's more...

A pie chart without any information on its content is probably not going to work as well as a chart with information, but we can figure out the locations... well worry not; we are going to revisit our old friends cos and sin to help us locate the dots on our circle, to enable us to add textual information on our newly created pie.

Revisiting Math.cos() and Math.sin()

We will start with adding a new global variable to store the color of our lines and then we will call it copyStyle:

var copyStyle = "#0000000000";

Now that we are right back into our init function, let's add it into our for loop just before the last line:

currentTotal+=data[i].value;

As expected, we will first set our new copyStyle variable as our fill and stroke value:

context.strokeStype = context.fillStyle =  copyStyle;

Our next step is to locate where in our pie we would like to draw a line out so that we can add the text:

midRadian = (currentTotal+data[i].value/2)/total*rad360;

To accomplish this, we will use a new variable that will store the mid-value between the last total and the new value (the center of the new slice). So far so good. Now we need to figure out how to get the x and y positions of that point. Lucky for us, there is a very easy way of doing it in a circle by using the Math.cos (for the x) and Math.sin (for our y) functions:

context.beginPath();
context.moveTo(Math.cos(midRadian)*radius,Math.sin(midRadian)*radius);
context.lineTo(Math.cos(midRadian)*(radius+20),Math.sin(midRadian)*(radius+20));
context.stroke();

Armed with our midRadian variable, we will get the value for a circle with a radius of 1, so all that is left for us to do is duplicate that value by our real radius to find our starting point. As we want to draw a line in the same direction to the arc externally, we will find the points of an imaginary circle that is larger; so for that we are going to use the same formula, but instead upgrade our radius values by 20, creating a diagonal line that is correlative to the arc.

All that is left for us to do is figure out what text we would want to have within our chart, using the same arc point with a larger circle size:

context.fillText(data[i].label,Math.cos(midRadian)*(radius+40),Math.sin(midRadian)*(radius+40));

Looks good... The only problem is that we don't have our values; let's add them and figure out the challenges involved with them.

Improving our bubbles' text format

In a real-world example, we would probably want to use a rollover if this was a live application (we will visit that idea in a later chapter), but let's try to figure out a way to create the chart capable of containing all the information. We stopped in our preceding line of code with a really large exterior circle (radius+40). Well that's because we wanted to slip in a new line of text right under, so let's do it:

context.fillText(formatToMillions(data[i].value) + "(" +formatToPercent(data[i].value/total) + ")" ,Math.cos(midRadian)*(radius+40),Math.sin(midRadian)*(radius+40) + 12);

It's a bit of a mouthful, but it's basically the same as the preceding line with a new line of text and an extra change, as we are shifting the y value by 12 pixels to account for the first line of text on the same area. To get this working, we are using two helper functions that format our text:

function formatToPercent(val){
  val*=10000;
  val = parseInt(val);
  val/=100;
  return val + "%"	
}

function formatToMillions(val){
  val/=1000000;
  return val + "Million";	
}

If you run the application in its current format, you will find that the text just doesn't look good on the page, and that is where the artist within you needs to sort things out. I've continued the sample in our source files until it felt right, so check it out or create your own variations from here on.

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

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