Monday, December 15, 2014

Making Some Pies

Shoofly Pie by Syounan Taji
My favorite kind of pie is Shoofly Pie, a molasses pie which originates among the Pennsylvania Germans. It is very similar to the English Treacle Tart, where golden syrup is used instead of molasses, which is also one of my favorite desserts when I'm in the U.K.

None of that has anything to do with the kinds of pies I made last week (before I got sick and spent several days barely awake). I made pie charts. You know, like doughnut charts, but without the hole in the middle. Both sound delicious but can't be eaten.

Also, don't confuse charts and graphs. It is my understanding that a graph is a type of chart that uses lines. Like a square is a type of rectangle.

Anyway, I wanted to take some of my data I capture from amphibian.com and plot it in a way that makes analyzing it easy. I am most interested in how many comics are accessed per day and which types of browsers people use to access the site. I have web services that generate the raw numbers from the server, so I wanted to find a JavaScript client library that could draw pretty pictures for me.

After experimenting with a few options, I went with Chart.js. Another popular recommendation was Data-Driven Documents, D3.js, but that was really overkill for my needs. I like to keep it simple.

Chart.js lets you take JSON data and render 6 different chart types using HTML5 Canvas. You can extend it to create your own additional chart types if you want, but the ones already included meet most needs: Line, Bar, Radar, Polar Area, Pie, and Doughnut. One of its best features is that it allows the charts to be responsive. When enabled, it resizes the canvas element as the parent element changes and the chart still looks good.

Using it on a web page is easy. First, just download the library and include it on your page:

<script type="text/javascript" src="/js/Chart.min.js"></script>

Now put a Canvas element, or elements, on your page where you want to draw the chart(s). There's a tricky thing about Canvases in that they really need width and height attributes, which is fine except when we want to have responsive charts that size with the browser. When going responsive, the trick is to just set the size very small but maintain the proportions, such as 80x60 instead of 800x600 and let Chart.js size it up for you - you won't even notice.

<div style="width: 50%">
  <!-- I really want this chart to fill the div automatically -->
  <canvas id="chart1" width="80" height="60"></canvas>
</div>

All that's left to do is organize your data in an appropriate way for the type of chart you'd like to draw, and pass it to the appropriate Chart function. Let's look at a simple line chart for example, but the Chart.js documentation has plenty of detail on all the other options plus more customizations.

var chartData = {
        "labels": ["A", "B", "C", "D", "E"],
        datasets: [
            {
                label: "Something",
                fillColor: "rgba(151,187,205,0.2)",
                strokeColor: "rgba(0,51,102,1)",
                pointColor: "rgba(151,187,205,1)",
                pointStrokeColor: "#fff",
                pointHighlightFill: "#fff",
                pointHighlightStroke: "rgba(220,220,220,1)",
                data: [33, 57, 42, 88, 101]
            }
        ]
    };

var opts = {
    "scaleGridLineColor": "rgba(0,0,0,.08)",
    "datasetStrokeWidth": 3,
    "responsive": true
};
 
var ctx = document.getElementById("chart1").getContext("2d");
var myChart = new Chart(ctx).Line(chartData, opts);

Line charts need a set of labels for the X-axis, and at least one set of data for drawing a line. You can actually draw more than one line on the same chart, useful when comparing data, which is why the datasets field is an array (even though in my example it only had one element).

Each dataset object should contain a label, color-related information for the lines and fills and points, and the set of values to plot on the Y-axis. Those values should in in an array given as the data field.

An options object can be used as well. There are a number of "global" chart options but each kind of chart has some specific options you can use. I customized the color of the scale grid lines, the stroke width of the data line, and made sure to set responsive to true.

All you need to do is pass the 2D context from the appropriate Canvas element into Chart and pass the the chart data and options to the chart type (see the final 2 lines above). You get back a reference to the chart, which you can use later to update the data and redraw if you want.

A chart that is always 50% of the page width

I was pleased with how simple it was to create and customize the simple charts I needed. I would recommend you check out Chart.js if you have similar needs on a project.

Sorry if you are disappointed by the lack of actual pie making in this blog. I know, I didn't even show how I made a pie chart! I did actually make some, after I made a line chart - but I'll let that be an exercise for the reader (or you could check out the amphibian.com repo on GitHub).

Amphibian.com comic for 15 December 2014