Working with data and SVG graphics


On a recent project we had a requirement to provide a number of game-like interactions which didn't really fit, design-wise, into the rather boxy constraints of HTML elements. Probably as recently as a couple of years ago you would have automatically turned to Flash to create these interfaces, but with a need to make the games work on mobile and other devices where Flash support is either absent or a battery drain we looked around for alternatives.

In the post-Flash rich-UI space there are currently two main options - Scalable Vector Graphics (SVG) and Canvas. SVG has actually been around a fairly long time, but adoption on the web has been held back until recently by browser support. It's the definition of vector (line-based) graphics in an XML document which are drawn to the screen, with the benefit that the drawing can be manipulated by altering the properties of each vector. Canvas, on the other hand, is a relative newcomer and thought of as part of the "HTML5" family of technologies. It's a bitmap (pixel-based) format so each update to a canvas object involves over-writing the pixels that were there before.

Both have their uses, and in fact we ultimately used both in the overall project in the places that suited their strengths. But for this particular one, a multiple choice quiz based on the relationships between people and objects, SVG seemed like a natural fit.

Using Raphäel

Based on past experience with it, I chose Raphäel as the SVG library to base the work on. While this was a great head start - Raphäel provides a nice API to work with the SVG DOM and appropriate fallbacks for older browsers - in previous uses I hadn't done much in the way of interactivity and this is where things started to get complicated.

Binding Javascript event handlers to SVG elements works comparably to HTML, and this is fine when a click or touch on an element affects only itself. In the context of a game where multiple elements need to be changed, it becomes a headache to keep track of state and what everything is supposed to be doing.

In HTML this problem has been largely solved with the rise of Javascript MVC libraries, where the state of a page or application is held as a model in Javascript and bindings to the DOM are used to update the UI based on changing data or user input. This was exactly what we needed for our game, but on initial investigation it looked like there wasn't really anything directly comparable for SVG.

At first the whole game area was created in SVG, but given this event/state issue and that there isn't much sophistication in the SVG 1.0 spec for text handling - especially wrapping of strings in a container element - we switched to rendering the multiple choice selections with HTML. This is the only part the user directly interacts with, and as HTML it could be bound directly to the Knockout viewmodel we stored the game state in. Changes in the model could then fire the appropriate functions to update the state of the SVG object and sanity could be preserved.

This reduced a lot of complexity and made the UI easier to manage but it still feels like a compromise solution as the smoother styling and scaling effects available in SVG couldn't be applied to the HTML parts of the game.

What else is out there

However Raphäel isn't the only SVG library out there, and other options might get closer to what we really needed. Pablo is described as being a combination of Raphäel, jQuery and Underscore for SVG, and an initial look shows a nice API with some useful stuff like duplication, templating and DOM traversal. As is often the way of these things, Pablo popped on to our radar just as the project was finishing.

D3.js is a popular charting and data visualation library which is able to transform documents based on changing data. However there's a higher level of complexity here and so in the constraints of the project there wasn't time to investigate it fully.

Another really interesting looking SVG library is Bonsai which is used as the basis of a Flash to HTML5 conversion service. And on the other side of the modern-rich-UI party, Canvas Query is a new tool positioned as a jQuery-style wrapper for the Canvas element.

What else is needed

While there are plenty of sophisticated options for pure charting in SVG, which can also handle data entering and leaving the object, it feels to me as if there is a missing link in a nice handler for interactivity and application state.

Or perhaps the solution is in one of the tools listed above and I haven't looked hard enough yet.

Either way, I'm going to look into this in more detail. Something that can act as a bridge between popular Javascript MVC libraries - the likes of Knockout, Backbone and Angular - and SVG rendering would be a useful tool, and if it doesn't already exist it would be worth creating.