Falcon80 Logo
JSON and Canvas


The canvas element in HTML4 provides a cool way to represent JSON data graphically. In the above example, the project statuses get updated at regular intervals by fetching project status details from a JSOn structure using AJAX. The server has the following JSON files:

Filename: JSON1.txt

{ "Projects":[{"Name":"Arcade","ProjectSize":3,"status":0}, {"Name":"Crimson","ProjectSize":5,"status":0}, {"Name":"Lilah","ProjectSize":4,"status":0}, {"Name":"Kanji","ProjectSize":6,"status":0}, {"Name":"Shuffle","ProjectSize":2,"status":0}], "month":"January", "year":2011 }

Filename: JSON2.txt

{ "Projects":[{"Name":"Arcade","ProjectSize":3,"status":20}, {"Name":"Crimson","ProjectSize":5,"status":10}, {"Name":"Lilah","ProjectSize":4,"status":50}, {"Name":"Kanji","ProjectSize":6,"status":30}, {"Name":"Shuffle","ProjectSize":2,"status":5}], "month":"January", "year":2011 }

Filename: JSON3.txt

{ "Projects":[{"Name":"Arcade","ProjectSize" : 3,"status": 30}, {"Name":"Crimson","ProjectSize" : 5,"status": 25}, {"Name":"Lilah","ProjectSize" : 4,"status": 55}, {"Name":"Kanji","ProjectSize" : 6,"status": 35}, {"Name":"Shuffle","ProjectSize" : 2,"status": 20}], "month":"February", "year":2011 }

Filename: JSON4.txt

{ "Projects":[{"Name":"Arcade","ProjectSize":3,"status":55}, {"Name":"Crimson","ProjectSize": 5,"status":40}, {"Name":"Lilah","ProjectSize":4,"status":70}, {"Name":"Kanji","ProjectSize":6,"status":45}, {"Name":"Shuffle","ProjectSize":2,"status":40}], "month":"March", "year":2011 }

Filename: JSON5.txt

{ "Projects":[{"Name":"Arcade","ProjectSize":3,"status":70}, {"Name":"Crimson","ProjectSize":5,"status":65}, {"Name":"Lilah","ProjectSize":4,"status":95}, {"Name":"Kanji","ProjectSize":6,"status":65}, {"Name":"Shuffle","ProjectSize" : 2,"status": 55}], "month":"April", "year":2011 }

Filename: JSON6.txt

{ "Projects":[{"Name":"Arcade","ProjectSize":3,"status":100}, {"Name":"Crimson","ProjectSize":5,"status":100}, {"Name":"Lilah","ProjectSize":4,"status":100}, {"Name":"Kanji","ProjectSize":6,"status":100}, {"Name":"Shuffle","ProjectSize":2,"status":70}], "month":"May", "year":2011 }

To try the above example, copy and paste the JSON data into their respective files and place them in the server. In real life, these files will be created in real time by server side scripts or by other upstream applications.

We will now write an AJAX function to retrieve the JSON files from the server.

<html>
<head>
<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">
<script type="application/javascript">
var count = 0;

function loadJSON()
{
var filename;
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{

// The response from the webserver is contained in the xmlhttp.responseText variable.
// Parse the file and assign the JSON object to JSONObject.

var JSONObject = JSON.parse(xmlhttp.responseText);

// Pass the parsed object as a parameter to the function draw().
// The draw() function uses the canvas element to represent JSONObject graphically.

draw(JSONObject);
}
}
count++;
if(count>=6) count = 1;

// Form the file names by varying count from 1 - 5 and appending
// it to the string JSON

filename = "JSON"+count+".txt";

// Fetch the files fromt the webserver using AJAX

xmlhttp.open("GET",filename,true);
xmlhttp.send();
}

We will have to update information from the server at regular intervals. Hence the above function is called every 5000 microseconds using the setInterval() function.

function init()
{
setInterval(function() {loadJSON();},5000);
}


The function init() is called from HTML

<body> tag so that it is executed when the page gets loaded.

<body onload="init()">

After the JSON file is fetched from the server and parsed, the draw() function displays the data graphically. It would be good to get an idea of how the canvas element works before looking at the below code. However, it is not necessary. The essense of this example is to show that once a JSON object is contained in a javascript variable, it can be used in many ways to serve your purpose.

function draw(JSONObject)
{
var canvas = document.getElementById("canvas");
if (canvas.getContext) {
var ctx = canvas.getContext("2d");
ctx.save();

// Set the colour and shadow properties for the images drawn on the canvas
ctx.shadowOffsetX = 3;
ctx.shadowOffsetY = 3;
ctx.shadowBlur = 3;
ctx.shadowColor = "grey";

// Draw the heading. The month and year are dynamic and are retrieved from JSONObject
heading = "Status of Projects in "+JSONObject.month+ " of "+JSONObject.year;
ctx.clearRect(0,0,850,340);
ctx.fillStyle = "black";
ctx.font = "20px verdana";
ctx.textAlign="left";
ctx.fillText(heading,30,20);

// Draw the pie charts representing status completions. The radius of the pie charts are proportional to the number of people working on each project
for(i = 0; i <5; i++)
{
ctx.fillStyle = "rgba(0,255,0,0.1)";
ctx.beginPath();
ctx.arc(circle[i].X,circle[i].Y,JSONObject.Projects[i].ProjectSize*10,0*Math.PI/180,360*Math.PI/180,false);
ctx.closePath();
ctx.fill();
ctx.fillStyle = "rgb(0,100,0)";
ctx.beginPath();
ctx.moveTo(circle[i].X,circle[i].Y);
ctx.lineTo(circle[i].X,circle[i].Y,circle[i].X+JSONObject.Projects[i].ProjectSize*10, circle[i].Y);
ctx.arc(circle[i].X,circle[i].Y,JSONObject.Projects[i].ProjectSize*10,0*Math.PI/180,(JSONObject.Projects[i].status/100)*360*Math.PI/180,false);
ctx.closePath();
ctx.fill();
}
ctx.restore();

// Update project name and completion status from the JSON Object
ctx.fillStyle = "black";
ctx.font = "13px verdana";
ctx.textAlign="center";
ctx.fillText("Project Name:",50,circle[0].Y+100);
ctx.fillText("Completion Status:", 65, circle[0].Y+130);
for(i = 0; i < 5; i++) { ctx.fillText(JSONObject.Projects[i].Name,circle[i].X,circle[i].Y+100);
string = JSONObject.Projects[i].status+"%";
ctx.fillText(string,circle[i].X,circle[i].Y+130);
}
}
}


Now, lets put it all together.

Javascript Code:

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<script> src="json2.js"></script>
<script type="text/javascript">
var count=0;
var x=30;
var y=150;
var heading;
var string;

// This function is to initialize the centre points for the pie charts
function Circles(X,Y)
{
this.X=X;
this.Y=Y;
}

var circle = new Array(5);

function initialize()
{
for(i = 0; i < 5; i++)
{
circle[i] = new Circles(x+150,y);
x+=150;
}
}

function init()
{
initialize();
setInterval(function() {loadJSON();},5000);
}

function draw(JSONObject)
{
var canvas = document.getElementById("canvas");
if (canvas.getContext) {
var ctx = canvas.getContext("2d");
ctx.save();

// Set the colour and shadow properties for the images drawn on the canvas

ctx.shadowOffsetX = 3;
ctx.shadowOffsetY = 3;
ctx.shadowBlur = 3;
ctx.shadowColor = "grey";
ctx.clearRect(0,0,850,340);
ctx.fillStyle = "black";
ctx.font = "20px verdana";
ctx.textAlign="left";

// Draw the heading. The month and year are dynamic and are retrieved from JSONObject

heading = "Status of Projects in "+JSONObject.month+ " of "+JSONObject.year;
ctx.fillText(heading,30,20);

// Draw the pie charts representing status completions. The radius of the pie charts are proportional to the number of people working on each project

for(i = 0; i <5; i++)
{

ctx.fillStyle = "rgba(0,255,0,0.1)";
ctx.beginPath();
ctx.arc(circle[i].X,circle[i].Y,JSONObject.Projects[i].ProjectSize*10,0*Math.PI/180,360*Math.PI/180,false);
ctx.closePath();
ctx.fill();
ctx.fillStyle = "rgb(0,100,0)";

ctx.beginPath();
ctx.moveTo(circle[i].X,circle[i].Y);
ctx.lineTo(circle[i].X,circle[i].Y,circle[i].X+JSONObject.Projects[i].ProjectSize*10, circle[i].Y);
ctx.arc(circle[i].X,circle[i].Y,JSONObject.Projects[i].ProjectSize*10,0*Math.PI/180,(JSONObject.Projects[i].status/100)*360*Math.PI/180,false);
ctx.closePath();
ctx.fill();

}

ctx.restore();
ctx.fillStyle = "black";
ctx.font = "13px verdana";
ctx.textAlign="center";
ctx.fillText("Project Name:",50,circle[0].Y+100);
ctx.fillText("Completion Status:", 65, circle[0].Y+130);

// Update project status labels

for(i = 0; i < 5; i++) { ctx.fillText(JSONObject.Projects[i].Name,circle[i].X,circle[i].Y+100);
string = JSONObject.Projects[i].status+"%";
ctx.fillText(string,circle[i].X,circle[i].Y+130);

}
}
}


function loadJSON()
{

var filename;
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{

// The response from the webserver is contained in the xmlhttp.responseText variable.
// Parse the file and assign the JSON object to JSONObject.

var JSONObject = JSON.parse(xmlhttp.responseText);

// Pass the parsed object as a parameter to the function draw().
// The draw() function uses the canvas element to represent JSONObject graphically.

draw(JSONObject);
}
}

count++;
if(count>=6) count = 1;

// Form the file names by varying count from 1 - 5 and appending
// it to the string JSON

filename = "JSON"+count+".txt";

// Fetch the files fromt the webserver using AJAX

xmlhttp.open("GET",filename,true); xmlhttp.send();

}
</script>
<title> Tracking Project Status Using JSON, AJAX, and Canvas </title>

<body onload="init()">
<canvas id="canvas" width = "900" height="400"></canvas>
</body></html>



Note:
To try out the above example, copy the code into a text editor and save it as a .html file. Place the .html file and the JSON files mention previously onto the server. Access the .html file using your browser.