Real-time graph using Javascript

Author: nme · Thursday, 20 January, 2011 · No comments · Tags: javascript ·

Post below describes solution which requires Raphaël JS to draw graph using SVG.
I've also made a cleaner version — html5 canvas real-time graph — enjoy!

This idea was wandering through my mind for quite some time now, and finally I got a project I'm working on where it will be perfect to fit. That is why I decided to try to put this idea to the test. Suprisingly, it works :)

I was never a fan of Flash technology which would solve real-time graphing very fast so I had to pick Javascript libraries that will do the work. One of them is jQuery, because I like to have clean code. The other is Raphaël JS — Javascript library which aims allowing web developers to draw using SVG.

So, here is the effect of "step" scrolling:

Full sources are published and dual licensed under MIT and GPL. The above example is called step.html.

As an alternative, there is also "smooth" scrolling example included, but unfortunately — it makes web browser to consume 100% time of one CPU core. It might not be a problem on a desktop computer, but some older laptops will most likely "feel" the issue. If you know how to solve the problem — please let me know.

The actual source code consists of three parts:

animatedGraph jQuery plugin

// animatedGraph jQuery plugin, requires jQuery and Raphael libraries
(function($) {
    $.fn.extend({
        animatedGraph: function(width, height, steps, max, single, many, ms) {
            var path = function(array, step, left) {
                var scale = height/max,
                    path = '',          
                    x=-left,            
                    y=0;                
                for (var i=0;i<array.length;i++) {
                    if (i) {            
                        path += "S" + [(x += step), (y = height — array[i]*scale), x, y];
                    } else {            
                        path += "M" + [-10, (y = height — array[i]*scale)]; 
                        path += "C" + [0, (y = height — array[i]*scale)]; 
                    }                   
                }               
                return path+'L'+(array.length*step+10)+','+(height+10)+' '+(-10)+','+(height+10)+'+z';
            };          
            return this.each(function() {
                var self = this;
                self.step = width/(steps-1);
                $(self)         
                    .css('width',width+'px')
                    .css('height',height+'px');
                self.r = Raphael(self, width, height); 
                self.data = many(steps);
                self.path = self.r.path(path(self.data, self.step, 0))
                    .attr({             
                        stroke: '#66f',         
                        fill: '#ddf',           
                        'stroke-width': 2,      
                        'clip-rect': ''+[0,0,width-1,height]
                    });                 
                setInterval(function() {
                    self.data.shift();  
                    self.data.push(single());
                    self.path.animate({path:path(self.data, self.step, 0)});
                }, ms);         
            });         
        }       
    }); 
})(jQuery);

Pseudo-random source data generator

// rotating across pseudo-random values array
var Rotator = function() {
    var self = this;
    self.data = [ 
        16,23,41,38,45,31,29,22,27,22,25,29,32,45,88,30,
        26,22,45,23,36,48,99,22,32,26,22,27,5,0,0,3,15
    ];  
    self.index = 0;
    self.single = function() {
        self.index += 1;
        if (self.index > self.data.length) {
            self.index = 1;
        }       
        return self.data[self.index-1];
    };  
    self.many = function(length) {
        var results = [];
        for (var i=0;i<length;i++) {
            results.push(self.single());
        }       
        return results;
    };  
};

The main function

$(document).ready(function() {
    var self = this;
    $('#animatedgraph-demo')
        .replaceWith(function() {
            return $('<div id="animatedgraph-demo"></div>');
        });     
    var rotator = new Rotator();
    $('#animatedgraph-demo')
        .animatedGraph(200, 50, 20, 100, rotator.single, rotator.many, 1000);
});

Leave a comment