There are performance advantages to using canvas over svg for drawing complex charts (however canvas is not necessarily always better). You can read more about d3-path and svg vs canvasin this blog post.
In this blog post I will be showing off an example d3fc component, which can render on an svg and canvas elements. This is a first step to creating canvas compatible chart components which we may eventually incorporate into d3fc.
First, the candlestick component. We need 2 separate internal functions to handle either svg or canvas rendering. The series generator function then calls either the svg or canvas render function depending on what type of DOM element was passed to it in the selection.
First, the candlestick generator, which uses the d3fc-shape candlestick to generate the ‘path’ for both canvas or svg. The default is svg, but you can set the context to a canvas context for drawing on canvas, which you will see in action in a minute.
To render to canvas -
and the SVG render -
Then the series creation function simply sets up the zoom behaviour, splits the data into up and down arrays (to colour the up and down candlesticks differently), then draws the chart using the appropriate render function.
Then in our main code we need to just generate the x and y scales, initialise the series, then call the series with the data with our d3 selection. In a simple case the code would look something likes this -
As you can see above, to compare performance I added some zoom functionality to the series.
I created this small application to demonstrate both charts side by side, so you can try out and feel the performance difference for yourself.
Also you can check out the full code here.
They perform equally with a low number of candlesticks, but as you increase this number, the svg becomes very laggy and unresponsive on zoom, because it is having to mutate a huge DOM path element, whilst the canvas keeps its smoothness for much longer, performing well even up to 20,000 candlesticks on my PC.
Try it yourself
At some point in the future, we may create some canvas series, or adapt the current series in a similar way to this component, to allow it to render to svg or canvas. But until then, if you want to start rendering your charts on canvas, the code in this post should give you an idea of how to implement your own canvas components.
d3-path is an abstraction over SVG path creation which uses the canvas element's Context2D interface. Previously creating path generation code involved a lot of concatenating SVG path commands like M0,0 or L2,2, and the somewhat more cryptic C70 20,120 20,120 10. Even with ES6 string interpolation such code can be incredibly hard to read (and write!).
When creating d3 visualisations it's common to want some form of responsive layout. However, SVG and canvas don't provide a native way to do this. Most examples found online either use fixed dimensions or resort to some form of manual layout to achieve the required effect. This post introduces an alternative approach using CSS and custom elements.