Sunday, February 3, 2013

Graphing with Flot: Controlling Series Color

I had the recent pleasure of working the Javascript-based Flot graphing library. It generates graphs by drawing on an HTML Canvas (it also has capability support for older IE). Flot is very easy to use yet provides a lot of customizable options. So far, I haven't found something that I wanted to change that I could not. However, without setting any (or very few) options, you get great looking graphs. Even with the automatic formatting, layout, and color selection, you might find times where some finer control is required.

I discovered that when working with multiple series, I wanted to have more control of the color selections. Occasionally, Flot picked a color too light or too close to another series. I also was adding/removing series from my graph and wanted to try to maintain the color assigned to a given series. Fortunately, there are both a series.color and global colors array options available that enables you to override the auto color picking algorithm in Flot. The color you set depends on what your trying to accomplish. Use the global option to create one master palette regardless of series. Assign a color to the series directly to maintain the color or derive it from the series data. In my test, I just used the global colors array to create a set of colors that Flot would use when drawing the series on the graph.

To get started, I copied a data set used in one of the Flot examples which created several series of data:



var data = [
{
id: "usa",
label: "USA",
data: [[1988, 483994], [1989, 479060], [1990, 457648], ...
},
{
id: "russia",
label: "Russia",
data: [[1988, 218000], [1989, 203000], [1990, 171000], ...
},
{
id: "uk",
label: "UK",
data: [[1988, 62982], [1989, 62027], [1990, 60696], ...
},
{
id: "germany",
label: "Germany",
data: [[1988, 55627], [1989, 55475], [1990, 58464], ...
},
{
id: "denmark",
label: "Denmark",
data: [[1988, 62982], [1989, 62027], [1990, 60696], ...
}
];


I also created a variable and set the fixed settings I was planning to use:


var options = {
series: {
stack: true,
},
yaxis: { min: 0, max: 1000000 },
xaxis: { tickDecimals: 0 }
};



In this case, I also used the Flot plugin to enable creating a stacked chart.

Now that the basics are out of the way, I can focus in on customizing my colors. The default setting is an empty array (don't make it null - it will generate an error):

options.colors = [];
$.plot($(".graph"), data, options);


flot-options-colors-default


I can just add colors that will be assigned in the same order as the series:

options.colors = ['red','orange','green','blue','purple'];
$.plot($(".graph"), data, options);


flot-options-colors-html-names


Or, I can get a little more fancy and use jQuery.Color to generate the colors. The benefit of using that library is you can work in the HSL color space and then convert to something Flot understands. I built two different generators - one creates a monochromatic set of colors by altering the lightness of a base color and the other rotates through a range of hue values while maintaining a constant saturation/lightness for all the colors:


// Shades of blue
options.colors = $.map( data, function ( o, i ) {
return jQuery.Color('blue').lightness(0.7-i/(len*1.2)).toHexString();
});

$.plot($(".graph"), data, options);


flot-options-colors-lightness


// Rotate from red to purple
options.colors = $.map( data, function ( o, i ) {
return jQuery.Color({ hue: (i*360/len), saturation: 0.95, lightness: 0.35, alpha: 1 }).toHexString();
});

$.plot($(".graph"), data, options);


flot-options-colors-hue


If you wanted to use the same approach to set the color directly on the series, you could use $.each over the data series and set o.color equal to the value returned by jQuery.Color(). The approach is pretty flexible and allows for a high degree of control over the colors generated. I put together a small interactive demo on my sandbox that enables switching between color schemes, changing the chart type, and showing/hiding different series. This is just a couple of ideas I was playing with when attempting to assign meaningful colors to the data series I needed to graph. It was a good starting point for exploring the many customizations available in the library.