Monday, April 26, 2010

Dynamic graphic chart with canvas

Hi,
I tried to use canvas ability to draw graphs, dynamic in this case, client-side without need of flash or whatever demanding to install plugin to our web browser. It works in almost all browser except IE...
Here is the code :


var mem = Array();var dataSpan = Array();var ctx;var timer;var inc=0;var scale;var initLimUp=200;var axisMid;var axisTop;

Init function including canvas context declaration, transformation to put the origin at left bottom (mor natural for me) and launching of the recursive main function.


function initGraph(){
axisTop = document.getElementById('axisTop');
axisMid = document.getElementById('axisMid');axisBot = document.getElementById('axisBot');
var canvas = document.getElementById('canv');
if (canvas.getContext){
ctx = canvas.getContext('2d');
//Put the origin at left bottom
ctx.transform(1, 0, 0, -1, 0, 200);
ctx.lineWidth = 5;ctx.lineJoin = 'round';
ctx.save();
timer = setInterval('process()', 500);
}
}
Main function

function process() {
dataGeneration();
scaling();
draw();
changeAxis();
}
Function used to generate values feeding the graph.

function dataGeneration() {
//A dummy way to generate data
mem.push((inc%20==0)?Math.random()*400:mem[mem.length-1]+25);
dataSpan=mem;
//We keep only the last 35 values
if(mem.length>35) {
dataSpan.shift();
}
inc++;
}
I add a y-axis scaling ability to fit the graph with the values displayed.

function scaling() {
//To find out what is the scaling to apply, I look for the highest value to display
//then I compare it to the original display size of the canvas (that mean I'll have to apply scaling to the original state of the canvas)
var dataToCheck = new Array();
dataToCheck = dataToCheck.concat(dataSpan);
dataToCheck.sort(sortNumber);
var max = dataToCheck[dataToCheck.length-1];
scale = 1/(Math.ceil(max/initLimUp));
}
Simple function to chnage the legend of y-axis regarding the current scale.

function changeAxis() {
axisTop.innerHTML=initLimUp/scale;
axisMid.innerHTML=initLimUp/scale/2;
}
Comparison function used to find out what is the highest value displayed.

function sortNumber(a,b) {return a - b;}
Drawing function:
  1. Clear the canvas
  2. Adjust scaling
  3. Add a plot for each value and join (stroke) them


function draw(){
//We need to restore to the original state to be able to apply scaling (due to my scaling calculation method)
ctx.restore();
//We need to save directly to keep the original state in the stack else next restore won't work
ctx.save();
//As we've restored the initial scale, we can clear the whole canvas efficiently
ctx.clearRect(0,0,350,initLimUp);
//Then after applying the current scale value we draw the graphic
ctx.scale(1,scale);
ctx.beginPath();
for(i=0;i < dataSpan.length;i++){
ctx.lineTo(10*i,dataSpan[i]);
}
ctx.stroke();
}
You can test the graph by clicking down the button under the graph.
0
0
0

No comments: