D3: Using Reusable Modules and Components

Demonstration of Reusable D3

Introduction:

This is a blog post describing how I put the "Demonstration of Reusable D3" demo together.

First up: the code broadly follows the reusable D3 approach as described by Mike Bostock, and as described in the Developing a D3.js Edge book (which I co-wrote with Christophe Viau, Andrew Thornton and Ger Hobbelt). That approach relies upon JavaScript closures and a couple of other techniques which I'm not going to go into the detail of here. If you want more information regarding such things, best thing is to look at Mike Bostock's article, the book, other examples of reusable D3 (such as Peter Cook's reusable circular heat chart), and Bocoup's Exploring Reusability with D3.js blog post (which is long and extensive!).

So this write-up describes the components and modules, the structure(s) I used to work with those components & modules, and how this all enabled me to pretty straightforwardly re-use various bits of code.

Before we get going, a bit of terminology:

  • From the book: We will call a "component" a reusable piece of code generating graphics, which doesn't represent a complete chart, but a part meant to be composed with other elements.
  • So, a module is a reusable piece of code that doesn't generate graphics, such as a module managing Json, or controlling a JavaScript timer.

And finally, a brief word on objects and object orientation. This approach embraces 'composition' rather than inheritance. So rather than rather than build creaky Heath-Robinson-like vertical contraptions (inheritance), we build onion-like structures (composition) that embrace other components. Just something to keep in mind.

Description of the SVG Elements in Use:

Main SVG Elements in Use in the Reusable D3 Demo

I'm hoping that the above illustration is pretty-much self-sufficient, but in case it isn't:

  • We've got two SVG elements, each within their own DIV.
  • Each 'face' (including the Corgi's), is a 'g' element.
  • Each pie chart, is a 'g' element.
Detail of the SVG Elements in Use in the Reusable D3 Demo

Each 'face' 'g' element is pretty simple. Contains a circle element, an image element, and then two further 'g' elements, one for each eye. Each eye 'g' element contains two circles, one for the actual eye, and one for the pupil.

The pie chart 'g' elements are equally pretty straightforward: a 'g' for each slice, a path element rendering the actual slice, and a text element for the slice text.

Model-View-Controller, and Code Re-Use:

One of the most powerful aspects of D3 is the ability to bind data to an on-screen element, but then update that data without directly needing to update the element. What? For example, let's assume I bind an array of three elements ['dog', 'cat', 'sock'] to a pie chart. Provided I hold onto that data in a variable, I can then update that data in a completely separate distance piece of code, then at some point in the future (lets say a timer event), the code that renders the chart has access to this data via the binding.

How does this help? Because it allows us to move towards a model-view-controller type pattern. I know that there are many MVC purists out there, which is why I caged the above with "type pattern". The code behind this demo broadly follows the MVC pattern.

And following (however broadly) the MVC pattern in the above demo helps us move towards reusable code - which is the key goal after all. We can start to think about: "which code does the rendering?" "what manipulates the data?" "what code responds to timers" ..... so on - and thus start to build distinct blocks of code, code that in the future we can re-use.

Components and Modules:

Modules and Components in Use in the Reusable D3 Demo

So what components did we create? (remembering that components are reusable bits of code that generate graphics). Two components:

  • A pie chart component.
  • A face manager component.

Each of the components is pretty simple: all they do is take the data given and render it. Each has a 'transform' function which is used to move the elements, but that's pretty much it. They're actually pretty simple.

There were various modules that I created: a module to handle JavaScript timers (for instance controlling when the Queen updates which element she looks at), and a module to handle loading and holding on the Json data.

Finally there are the controller modules. These are by far the largest blocks of code, and are the heart of the application. All events are directed to the controllers, all data is manipulated by the controllers, and all rendering is kicked off by the controllers.

Each controller makes its own use of the d3.timer animation timer, and has its own "tickFn" to process d3.timer ticks.

Most and Least Reusable:

So has this actually produced reusable code?

The most reusable bits of code are the timer and json modules, the faceManager I've used elsewhere (in another application I'm putting together), and the pie chart should be reusable.

The least reusable bits are the controllers, but their structures are certainly something I can use again.

So, I'd say yes. For me yes.

Thanks is Due

I've been slowly ploughing my way through D3 books and examples for well over a year or so, and many people's examples, snippets, bits'n'bobs are all in someway incorporated in all of this. So, much thanks to: Mike Bostock and Jason Davies for creating D3; fellow authors: Christophe Viau, Andrew Thornton and Ger Hobbelt - from whom I learnt buckets; Mike Dewar for the book and samples; Scott Murray for the book and samples; Ian Johnson for the various examples out there; and https://bl.ocks.org/j0hnsmith for the pie examples. And the many others I've forgotten. Thanks!