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.
|