Quineloop

['Gautam Chekuri', 'gautam.chekuri@gmail.com', 'http://github.com/gautamc']
[Observe ∿ deconstruct ∿ Generalize ∿ Reflect ∿ Repeat]

« Back to /index

------------

Building a liquid html5/canvas charting widget using jQuery and backbone.js – I

01 Jan 2012

ChartView is an unambitious attempt to build a HTML5/JS charting widget using jQuery and backbone.js.

The goals I’ve set for this widget are:

  1. It should be easy to render multiple charts on the same page.
  2. It should be possible to set the height/width to a fixed pixel value or a percentage value.
  3. It should display the grid and axes.
  4. It should allow “overlay information bubbles” to be displayed.
  5. It should work on tablet/smartphone browsers (android for sure – since I have access to android devices)

The approach I figured I’d take can be summed up as follows:

Set the height & width of the canvas element in percentages and use jQuery as much as possible.

=> Implementing a liquid canvas element, takes more work then simply setting the elements height and width in percentages. Essentially, the canvas will scale depending on its height/width values and what was 1px before scaling, isn’t 1px anymore. Initially, this might sound like something we want, but we quickly see that the plot lines we draw would not remain of constant width – they would thicken as height/width values (in %) increased. Hence, the only way out is to set the height/width programmatically via javascript.

=> Hence, given this requirement of setting the height/width programmatically via javascript, I figured the best way to achieve liquid charts was to leverage jQuery’s height and width methods.

This approach involves, programmatically creating a canvas element and appending it to a div – which I refer to as a “canvas_holder”. In the markup, we can specifiy the height&width of the “canvas_holder” div either in percentages or fixed pixels.

For example, the chart rendered in the “canvas_holder” div given below spans across the entier width and height of its enclosing element:


  <div id="canvas_holder_5" align="center" style="margin-top: 20px; width:100%; height:100%;">
  </div>

A fixed width chart could be rendered via the following markup:


  <div id="canvas_holder_4" align="center" style="margin-top: 20px; width:600px; height:300px;">
  </div>

If we wanted to use a liquid grid style layout and render a multi-column chart placement, we could do something like this:


  <div style="float: left; clear: none; width: 45%;">
    <div id="canvas_holder_1" align="center" style="height:50%;">
    </div>
  </div>

  <div style="float: right; clear: none; width:45%;">
    <div id="canvas_holder_2" align="center" style="height:50%;">
    </div>
  </div>

Essentially, the markup listed above doesn’t explicitly set the width of the canvas_holder div. Because the two canvas_holders are positioned via their enclosing divs, the canvas_holder’s width is inherited from its respective enclosing div – jQuery’s height() and width() methods take care figuring out the width in pixels and the chart widget uses this information to build the the actual canvas element inside the “canvas_holder” div.

Encapsulate the widget as a backbone.js view object.

=> After defining the markup required for rendering the chart, we next intialize the chart this way:


  var chart_view_1 = new ChartView({id:"canvas_holder_1"});
  chart_view_1.render(); // Draw's that chart
  chart_view_1.reset(); // Reset's the chart so that it can be redrawn

=> ChartView, is a backbone.js view object. Its constructor would eventually accpect multiple arguments that will enable us to control how/what the chart renders. For now, the JS object that is passed to the ChartView constructor needs to have one key/value pair – for specifiying the id of the canvas_holder div.

=> Personally, for me the most interesting part is the programming that actually renders the chart based on the input data/series. This, intresting part is all inside ChartView. The input data would be implemented via a backbone.js model – something I will be doing in the coming days.

The two major concepts/details that I’ve figured out while implementing this present version of ChartView are:
a) Drawing the axes and the plot line based on the range of input data
b) Scaling the X & Y axes so that they fit the input data in the most optimal way.

Since, these details involve a minor amount of math, I figured I will describe them in a different blog post. I am sure these details are trivial for programmers who’ve already worked on charting libraries and such. I am finding that figuring these minor “math details” is enabling me a better programmer :-)

Cross Browser compatibility

=> For now, I am aiming to make the widget follow the html5 canvas standard. I am not particularly bothered about IE8 support. I aim to first concentrate on the widget object’s elegance and depend on jQuery for Browser compatibility as much as possible. Hence, for now I check the widget in Firefox and Chrome. Once, the object is functionally, I will work backwards to fix/address compatibility issues with other browsers.

An Example


Draw Chart | Reset Chart


URL to more Examples

-----------

« Back to /index