Sparklines.js is a simple javascript utility for building sparklines. It has support for displaying lines at percentage points (for example, the 0.25 percentage point is the equivalent of Q1, 0.5 is Q2 (the median), and 0.75 is Q3), and at fixed values in terms of your data set. (You might want lines at 80,120 in a chart of blood pressure values, for example, where the data points would be something like 100,50,60,70,100 and so on, to indicate the points outside of normal range.)
The sparklines will size themselves appropriately to any size canvas they are given. Be wary that charts can tell very different stories depending on how they are sized, and that you are responsible for giving a reasonable size for the chart to display itself on.
Charts can be displayed via line charts, or via bar charts, and allow for a high degree of customization. In addition, there is support for demarcating absolute values within the values, and also support for displaying lines at certain percentiles (for example, you might wish to display lines at the 25th and 75th percentile). Beyond that, it is possible to fill in the areas between two percentile or two absolute value lines, which is a helpful visualization to showing which values lie between the two points.
Other statistical analysis functions will likely be added over time. Feel free to suggest anything that you feel is missing.
Oh, and if you're just here for a minute, here are some of my favorite sparklines from the examples:
Sparklines.js is currently piggybacking off of Processing.js to provide its rendering, but will likely remove that dependency once the pace of development slows down and it becomes clear which features will need to be extracted. Processing.js is excellent for prototyping projects, and is very pleasant to work with, and the decoupling's justification is reduction of filesize by removing functionality that is not used by (the fairly simple demands of) Sparklines.js.
A quick note about the format of data sources that are given to the sparklines. The expected standard data is simple: an array of height values (absolute values, since they'll be scaled to the size of the sparkline). However, you might want to pass it a much more complex data set. You have two options. First, you can extract the heights form your data set before passing it to the sparkline, or you can write a function that instructions the sparkline how to do that itself.
Here is a simple example demonstrating how the later method works.
var a = {'height':100,'name':"A"};
var b = {'height':150','name'="B"};
var data = [a,b];
var extract = function(x) { return x.height; };
var opts = {"parse_height":extract};
new Sparkline("canvas_id", data, opts);
This should allow sufficient flexibility for using custom data sets with sparklines.
Scaling data is very simple. By default BarSparklines scale from zero to max, and LineSparklines scale from min to max. However, you can customize this behavior.
For example, a line sparkline scaling from zero to max.
var opts = {'scale_from':0};
var data = [1,2,3,4,5,6];
new Sparkline("canvas_id",data,opts);
And a bar sparkline scaling from min to max is easy as well.
var opts = {'scale_from':undefined};
var data = [1,2,3,4,5,6];
new BarSparkline("canvas_id",data,opts);
And finaly a line sparkline scaling from 50 to 150.
var opts = {'scale_from':50,'scale_to':150};
var data = [1,2,3,4,5,6];
new Sparkline("canvas_id",data,opts);
This should provide sufficient flexibility to size the chart's viewport to emphasize the trend in the data that is particularly interesting to you.
The first type of Sparkline is the line sparkline, which represents data in a simple line format. Be wary that they can tell strikingly different stories depending on their height and width.
A simple sparkline.
var data = [100,500,300,200,400,500,400,400,100,200];
new Sparkline('simple1', data).draw();
The same sparkline, with excessive padding, in a taller canvas.
var data = [100,500,300,200,400,500,400,400,100,200];
var opts = {'left_padding':50,'right_padding':50,'top_padding':25, 'bottom_padding':25};
new Sparkline('simple2',data, opts).draw();
The same sparkline, with no padding, drawn in a longer canvas.
var data = [100,500,300,200,400,500,400,400,100,200];
var opts = {'left_padding':0,'right_padding':0,'top_padding':0, 'bottom_padding':0};
new Sparkline('simple3',data, opts).draw();
Let's change up the colors.
var data = [100,500,300,200,400,500,400,400,100,200];
var opts = {"background":"#FFEEDD","stroke":"#001122","average_color":"#FF9933"};
new Sparkline('simple4',data, opts).draw();
Well, it would be kind of neat to see the median (Q2).
var data = [100,500,300,200,400,500,400,400,100,200];
var opts = {"percentage_lines":[0.5]};
new Sparkline('simple5a',data,opts).draw();
Well, lets remove the line at Q2, and have them at Q1 and Q3 instead.
var data = [100,500,300,200,400,500,400,400,100,200];
var opts = {"percentage_lines":[0.25,0.75]};
new Sparkline('simple5',data,opts).draw();
It would kind of helpful to color the interquartile range.
var data = [100,500,300,200,400,500,400,400,100,200];
var opts = {"percentage_lines":[0.25,0.75],"fill_between_percentage_lines":true};
new Sparkline('simple6',data,opts).draw();
Lets see that with Q1, Q2, and Q3, with the iterquartile range colored, and a richer dataset.
var data2 = [100,200,500,1000,600,900,300,500,800,800,900,1000,50,40,200,100,900,300,400,400,600,700,800,900,700,800,50,100,100];
var opts = {"percentage_lines":[0.25,0.5,0.75],"fill_between_percentage_lines":true};
new Sparkline('simple7',data2,opts).draw();
Okay, now lets customize the hell out of this, and shrink it down to a much smaller size that might fit well in a blog entry or merged into a simple webapplication.
var data2 = [100,200,500,1000,600,900,300,500,800,800,900,1000,50,40,200,100,900,300,400,400,600,700,800,900,700,800,50,100,100];
var opts = {
"percentage_lines":[0.25,0.5,0.75],"fill_between_percentage_lines":true,
"left_padding":1,"right_padding":1,"top_padding":1,"bottom_padding":1,
"background":"#FFFFFF","stroke":"#444444","percentage_color":"#AAAAFF",
"percentage_fill_color":"#CCCCFF"
};
new Sparkline('simple8', data2, opts).draw();
But, you might not want to draw lines at the quartiles (or at whatever arbitrary percentage of entries), you might want to draw lines at certain values instead. For example, you might want to indicate the normal range of blood pressure in a patient.
var data3 =
[120,130,80,100,90,105,95,60,70,75,70,90,100,110,120,130,150,100,50,80,90,100,110,110];
var opts = {"value_lines":[80,120],"top_padding":5,"bottom_padding":0,"fill_between_value_lines":true};
new Sparkline('simple9', data3, opts).draw();
For fun, lets add some percentage lines into the mix as well.
var data3 =
[120,130,80,100,90,105,95,60,70,75,70,90,100,110,120,130,150,100,50,80,90,100,110,110];
var opts ={"value_lines":[90,110],"top_padding":5,
"bottom_padding":0,"fill_between_value_lines":true,
"percentage_lines":[0.25,0.75],"percentage_color":"#FF6666"
};
new Sparkline('simple10', data3, opts).draw();
new Sparkline('simple10', data3, opts).draw();
Lets see that at a few different sizes. The one above it 500px by 200px. Lets try it at 300px by 100px.
And maybe at 100px by 50px. (Although, we'd really want to reduce the padding, since its a bit too much at this small size.)
Bar sparklines can be clearer about conveying some types of information than line sparklines. They are more explicit about exact quatities, but are often less effective at exposing trends within the data they are graphing.
Lets start with the simplest of bar sparklines.
var data3 =
[120,130,80,100,90,105,95,60,70,75,70,90,100,110,120,130,150,100,50,80,90,100,110,110];
new Sparkline('bar11', data3).draw();
And add a nice filled region between Q1 and Q3.
var data3 = [120,130,80,100,90,105,95,60,70,75,70,90,100,110,120,130,150,100,50,80,90,100,110,110];
var opts = {'percentage_lines':[0.25,0.75],"fill_between_percentage_lines":true};
new Sparkline('bar2', data3).draw();
Notice that the percentage lines and fill between them extend beyond the bars. Personally, I think that looks better, but you may want to disable that.
var data3 = [120,130,80,100,90,105,95,60,70,75,70,90,100,110,120,130,150,100,50,80,90,100,110,110];
var opts ={'percentage_lines':[0.25,0.75],"fill_between_percentage_lines":true, "extend_markings":false};
new Sparkline('bar3', data3).draw();
Maybe we want less space between lines, and some extra padding from the sides, and while we're at it lets make that extra padding for the percentage lines and filling a bit wider as well.
var data3 =[120,130,80,100,90,105,95,60,70,75,70,90,100,110,120,130,150,100,50,80,90,100,110,110];
var opts = {'percentage_lines':[0.25,0.75],"fill_between_percentage_lines":true,
'padding_between_bars':2,"left_padding":30,"right_padding":30,
'marking_padding':16};
new Sparkline('bar4', data3).draw();
Our old friends, value lines, are still available to draw lines at values instead of at percentages points.
var data3 =[120,130,80,100,90,105,95,60,70,75,70,90,100,110,120,130,150,100,50,80,90,100,110,110];
var opts = {'value_lines':[85,115]};
new BarSparkline('bar5',data3,opts).draw();
And we can fill between the value lines too. And take away the spacing between bars, if we feel like it.
var data3 =[120,130,80,100,90,105,95,60,70,75,70,90,100,110,120,130,150,100,50,80,90,100,110,110];
var opts = {'value_lines':[80,120],"fill_between_value_lines":true,"padding_between_bars":0,"bottom_padding":3};
new BarSparkline('bar6',data3,opts).draw();
The simplest way to customize a sparkline is to pass in a dictionary of modified attributes. This is the technique that is used in all the examples on this page. It looks something like this:
var data = [100,500,300,200,400,500,400,400,100,200];
var opts = {'left_padding':50,'right_padding':50,'top_padding':25, 'bottom_padding':25};
new Sparkline('simple2',data, opts).draw();
If you end up doing a large number of similar sparklines, you may begin to feel that passing the arguments in each time is getting a bit redundant. In such a case, you can subclass the Sparkline or BarSparkline classes to look the way you prefer. For example:
var MySparkline = function(id,data,mixins) {
this.background = "rgba(255,255,255,1);";
this.stroke = "rga(100,100,100,.7);";
this.top_padding = 3;
this.bottom_padding = 3;
this.left_padding = 6;
this.right_padding = 6;
this.init(id,data,mixins);
}
MySparkline.prototype = new Sparkline();
new MySparkline("canvas_a",[1,2,3,4]);
If you wanted to customize BarSparkline instead, you
would change the line
MySparkline.prototype = new Sparkline();
to
MySparkline.prototype = new BarSparkline();.
Right click here to download the minified sparklines.min.js file.
Its also very easy to build your own deploy copy to have the most recent version. Simply check out the current project from Git and from the main project directory type:
./scripts/deploy.sh
and a deploy copy will be created named sparklines.min.js
which contains all necessary code merged into one file.
There is a public repository available at github for those interested in the most recent releases or contributing.
This project is inspired by a number of sources, and almost all of those sources have appeared in my life as the result of readings and research direct my way by J.D. Hollis. Beyond that, J.D. has also provided feedback about the project, along with a critical eye.
There is a huge amount of thinking about informational design going on at the moment, and this project might be described as a small attempt to make a small piece of that information easier to take advantage of.
Feel free to send requests, comments and complaints about this project
to lethain@gmail.com.
This project has been released under the MIT License by Will Larson