SVG is the preferred choice for D3. But when you expect a lot of DOM nodes (yes, in the case of Lightbeam) you need to start worrying about the DOM performance and have to take the call to step out of the SVG comfort zone. We chose Canvas over SVG for Lightbeam 2.0!
In this post, I would like to highlight the key points of drawing and interactivity on the HTML5 Canvas element.
In our case, we followed the first approach – using D3 solely for its functional purpose (D3’s force layout algorithm) and then drawing onto the canvas.
Normally, when you follow this approach, you are trading off D3’s super rich data binding and joining functionality. It means you’re only drawing your graph once – you’re not expecting new data that would require a graph redraw or update. This is why D3 with some dummy HTML nodes is a preferred way in order to retain the data binds and joins. D3’s joins are a way to dynamically update the graph without having to redraw the whole thing over and over again.
The dummy HTML element approach
Here is an example of using custom aka dummy HTML elements to render D3 on canvas.
custom is definitely not a standard DOM element type, so it will not be rendered in any way and will live only in memory (virtual DOM). It is used as a container for other dummy nodes.
How does Lightbeam update dynamically without D3 joins?
Even though we followed the first approach, Lightbeam has dynamic updates. Luckily, D3’s force layout algorithm takes care of the new
link updates/additions and we managed to use D3 only for its functionality without the dummy element approach. Here is the PR.
Interactivity on the canvas
Canvas is a single DOM element and mouse interactions on the canvas can be sometimes tricky because you don’t have independent access to the nodes and links (or any graph element). In our case, we have the following interactions:
- On hover over the nodes (websites) show tooltips with the name of the website
- Drag the graph
- Zoom in and zoom out the graph
- Panning – shifting the view of the graph
At the time of writing this blog post, only tooltip based interactivity is achieved. PR
I shall explain tooltip based canvas interactivity in the next post.
- Dummy element approach
- D3 and canvas – 1
- D3 and canvas – 2
- Pluralsight’s canvas based visualisation tutorial
- D3 and canvas in 3 steps
Initial performance results
I have never done performance testing using browser devtools. When we migrated from SVG to Canvas I was curious to know the performance results of using canvas. For a given small sample of websites, here are the test results. Canvas has a rendering score of 4.3 milliseconds 🙂