Book Image

HTML5 Graphing and Data Visualization Cookbook

By : Ben Fhala
Book Image

HTML5 Graphing and Data Visualization Cookbook

By: Ben Fhala

Overview of this book

The HTML5 canvas tag makes creating any plot shape easy, all you have to do then is fill it with exciting visualizations written in JavaScript or using other visualization tools. "HTML5 Graphing and Data Visualization Cookbook" is the perfect break into the world of Canvas, charts, and graphs in HTML5 and JavaScript. In this book we will go through a journey of getting to know the technology by creating and planning data-driven visualizations. This cookbook is organized in a linear, progressive way so it can be read from start to finish, as well as be used as a resource for specific tasks.This book travels through the steps involved in creating a fully interactive and animated visualization in HTML5 and JavaScript. You will start from very simple "hello world"ù samples and quickly dive deeper into the world of graphs and charts in HTML5. Followed by learning how canvas works and carrying out a group of tasks geared at taking what we learned and implementing it in a variety of chart types. With each chapter the content becomes more complex and our creations become more engaging and interactive.Our goal is that by the end of this book you will have a strong foundation; knowing when to create a chart on your own from scratch and when it would be a good idea to depend on other APIs.We finish our book in our last two chapters exploring Google maps and integrating everything we learnt into a full project.
Table of Contents (17 chapters)
HTML5 Graphing and Data Visualization Cookbook
Credits
About the Author
About the Reviewer
www.PacktPub.com
Preface
Index

Creating complex shapes


It's time to take everything we learned and integrate it into the most complex shape we have seen so far, the Star of David. This star is part of the flag of Israel (one of my favorite flags in the world ;)). We need to take a roundabout before we can create it by visiting the magical world of sine and cosine.

You got to love it, right? I know many people fear cosines and sines but actually they are really easy and fun to work with. Let's break them down here in a more programming-for-drawing type of way. The most basic idea is that you have a triangle that has a 90 degree angle. You have some information about this triangle, and that's all you need to be able to start working with sine and cosine. Once you know that you have a 90 degree angle and know the sine/cosine, you have all the information you need and with it you can discover any missing information. In our case we know all the angles and we know the length of the hypotenuse (it's our radius; take a look at the image with the circle to see it in action). In JavaScript, the methods Math.cos() and Math.sin() are both representing a circle with a radius of one located on the (0,0) point on the screen. If we input the angle we are looking for into the sin function, it would return the x value (in this case the length of the adjacent) and the cos function would return the length of the opposite, in our case the required value y.

I've made a nice video which goes deeper into the logic. You can check it out at http://02geek.com/courses/video/58/467/Using-Cos-and-Sin-to-animate.html.

Getting ready

The easiest way to understand how sine/cosine work is by a live example, and in our case we will use it to help us figure out how to create the Star of David in the flag of Israel. We will take a step back and learn how we figured out the points on the screen to create the shapes. Again we will be skipping the creation of the HTML file and will go right into the JavaScript code. For an overview of how to get your HTML set, please review the Graphics with 2D canvas recipe.

How to do it...

After creating the JavaScript file add the following code in your init function.

  1. Create our basic canvas variables:

    var canvas = document.getElementById("israel");
    var wid = canvas.width;
    var hei = canvas.height;
    var context = canvas.getContext("2d");
  2. Define one degree in radians. We do that since Math.cos and Math.sin expect a radian value and not a degree value (radian is one degree measured in radians):

    var radian = Math.PI/180;
  3. Create a tilt variable. This variable will define the tilt of the triangle that will be created. Imagine the triangle is in a circle and we are rotating the circle with this tilt variable:

    var tilt = radian*180;
  4. Define the center point of the canvas:

    var baseX = wid / 2;
    var baseY = hei / 2;
  5. Set the radius of the invisible bounding circle of the Star of David:

    var radius = 24;
  6. Define the height of the strips in the flag:

    var stripHeight = 14;
  7. Define a line width:

    context.lineWidth=5;
  8. Create two triangles (one tilted and one not):

    createTrinagle(context,
      baseX+ Math.sin(0) * radius, baseY + Math.cos(0) * radius,
      baseX+ Math.sin(radian*120) * radius, baseY + Math.cos(radian*120) * radius,
      baseX+ Math.sin(radian*240) * radius, baseY + Math.cos(radian*240) * radius, 
      null,"#0040C0");
    
    createTrinagle(context,
      baseX+ Math.sin(tilt) * radius, baseY + Math.cos(tilt) * radius,
      baseX+ Math.sin(radian*120+tilt) * radius, baseY + Math.cos(radian*120+tilt) * radius,
      baseX+ Math.sin(radian*240+tilt) * radius, baseY + Math.cos(radian*240+tilt) * radius, 
      null,"#0040C0");
  9. Draw flag strips:

    context.lineWidth=stripHeight;
    context.beginPath();
    context.moveTo(0,stripHeight);
    context.lineTo(wid,stripHeight);
    context.moveTo(0,hei- stripHeight);
    context.lineTo(wid,hei- stripHeight);
    context.closePath();
    context.stroke();
  10. Create the createTriangle function:

    function createTriangle(context,x1,y1,x2,y2,x3,y3,fillColor,strokeColor){
      context.beginPath();
      context.moveTo(x1,y1);
      context.lineTo(x2,y2);
      context.lineTo(x3,y3);
      context.lineTo(x1,y1);
      context.closePath();
      if(fillColor) {
        context.fillStyle = fillColor;
        context.fill();	
      }
      if(strokeColor){
      context.strokeStyle = strokeColor;
      context.stroke();
      
      }
    }

You are done. Run your application and you will find the flag of Israel with the Star of David in the center of the flag.

How it works...

Before we dig into the creation of the flag and how it was done, we need to understand how we locate points in a circle. To do so let's look at a simpler example:

var rad = Math.PI/180;	
context.fillStyle = "#FFDE00";
context.arc(wid / 2, hei / 2, 30, 0, 2 * Math.PI, false);
context.fill();
context.beginPath();
context.strokeStyle = "#ff0000";
context.lineWidth=6;
context.moveTo(Math.sin(0) * 30 + wid / 2, Math.cos(0) * 30 + hei/2);
context.lineTo(Math.sin(rad*120) * 30 + wid / 2, Math.cos(rad*120) * 30 + hei/2);
context.stroke();

The following is the output the code will generate:

Although a circle, in our human-friendly head, is a shape that has 360 degrees, it's actually best represented in most programming languages in radians.

Radians are just like degrees, only instead of being human-friendly numbers between 0 and 360 these are numbers between 0 and two times Pi. You might be wondering what Pi is, so a bit more on Pi. Pi is in essence the value that is created when you take the circumference of any circle and divide it by the diameter of the same circle. The result that would come back would be Pi or about 3.14159. It is a magical number and the good news is you don't need to know much more about it if you don't want to. All you need to know is that 3.142 is equal to half of a circle. With that fact we can now divide Pi by 180 to get a value in radian that equals one degree:

var rad = Math.PI/180;

We then create a circle with a radius of 30 in the center of the screen, to help us visualize this, and move on to start creating a line that will start at angle 0 of our circle and end at angle 120 (as we want to create a triangle 360/3).

context.strokeStyle = "#ff0000";
context.lineWidth=6;
context.moveTo(Math.sin(0) * 30 + wid / 2, Math.cos(0) * 30 + hei/2);
context.lineTo(Math.sin(rad*120) * 30 + wid / 2, Math.cos(rad*120) * 30 + hei/2);
context.stroke();

Let's break down the most complex line:

context.lineTo(Math.sin(rad*120) * 30 + wid / 2, Math.cos(rad*120) * 30 + hei/2);

As Math.sin and Math.cos return a value for a radius of 1, we will multiply any value returned by the radius of our circle (in this case 30). In the parameters of Math.sin and Math.cos, we will provide the exact same values; in this example 120 radians. As our circle would be centered at the top left-hand side of the canvas we want to shift the circle to start from the center of the screen by adding to our values wid/2 and hei/2.

At this stage, you should know how to find points on a circle, and with that how to draw lines between two points. Let's go back to our flag of Israel and take a deeper look into the new function createTriangle. It was based on the function fillTriangle created in the Creating shapes using paths recipe.

function createTriangle(context,x1,y1,x2,y2,x3,y3,fillColor,strokeColor){

...

  if(fillColor) {
    context.fillStyle = fillColor;
    context.fill();	
  }

if(stokeColor){
    context.strokeStyle = fillColor;
    context.stroke();	

  }

}

I've highlighted the new components of this function compared to the function fillTriangle. The two new parameters fillColor and strokeColor define if we should fill or stroke the triangle. Notice that we moved the strokeStyle and fillStyle methods to the bottom of our function to reduce our code footprint. Great! We now have a modern triangle creator that could deal with the Star of David.

There's more...

OK, time to connect the dots (literally speaking) and create the flag of Israel. Looking back at our original code we find ourselves using the createTriangle function twice to create the full Star of David shape. Let's take a deeper look at the logic here by looking at the second triangle (the one that is turned upside down):

createTriangle(context,
  baseX+ Math.sin(tilt) * radius, 
  baseY + Math.cos(tilt) * radius,
  baseX+ Math.sin(radian*120+tilt) * radius, 
  baseY + Math.cos(radian*120+tilt) * radius,
baseX+ Math.sin(radian*240+tilt) * radius,
  baseY + Math.cos(radian*240+tilt) * radius, null,"#0040C0");

We are sending in three points on the virtual circle to create a triangle. We split our virtual circle to three equal parts and find the point values at the 0, 120, and 240 degrees. This way if we drew a line between these points we would get a perfect triangle in which all of the sides were equal.

Let's take a deeper look at one of the points sent to the createTriangle function:

baseX + Math.sin(radian*120+tilt) * radius, 	
baseY + Math.cos(radian*120+tilt) * radius

We start from baseX and baseY (the center of the screen) as the center point of our circle before we figure out the actual point gap from that base starting point. We then add to it the value that we get from Math.sin and Math.cos respectively. In this example, we are trying to get 120 degrees plus the tilt value. In other words, 120 degrees plus 180 degrees (or 300 degrees).

To make it easier to comprehend, in pseudocode it would look similar to the following code snippet:

 startingPositionX + Math.sin(wantedDegree) * Radius 
 startingPositionY + Math.cin(wantedDegree) * Radius 

Not much more to say besides congrats. We just finished creating another flag and in the process, learned how to create complex shapes, use math to help us figure out points on the screen, and mix together different shapes to create more advanced shapes.