Reputation:
I have to build d3 visualisations that work well both on tablets, Desktop displays, and in some cases very very large 4k+ high resolution cinema size displays.
So I'm trying to figure out what the trade off is between using SVG's 'viewBox' attribute with 'preserveaspectratio' vs having a resize function called to re-render on window resize events and use absolute values. Most examples, such as this blog entry (http://eyeseast.github.io/visible-data/2013/08/28/responsive-charts-with-d3/) suggest the latter in which I do something like this:
d3.select(window).on('resize', resize)
resize() {
// rerender each individual element with the new width+height of the parent node
d3.select('svg')
.attr('width', newWidth)
//etc... and many lines of code depending upon how complex my visualisation is
}
However, why can't I just use SVG viewBox to let my SVG resize like so:
d3.select('svg')
.attr( 'preserveAspectRatio',"xMinYMin meet")
.attr("viewBox", "0 0 900 500")
.attr('width', '100%')
I just make everything assuming that my width and height are 900x500px (or whatever), and leverage the fact that SVG is a vector format that takes care of all the fiddly details such as text sizes and margins. I'm struggling to see why so many people when giving examples of responsive or scalable visualisations using D3 favour a resize() function, and I'm very worried that I'm missing something if I go down the viewBox route.
So in addition to what mef has said below, one thought is that with a viewBox I'm stuck with a particular aspect ratio. So I might want the height of the visualisation to stay fixed such as in the case of a line or bar chart, but it has it be responsive on its width. With a fixed aspect ratio this isn't possible as changes in width require changes in height. This case requires a resize() function that re-renders to fit to the new aspect ratio.
So although a viewBox with a fixed aspect ratio is significantly easier to implement, there are a lot of common cases that require greater control, which necessitates a resize() function and explains the community preference for the more complicated solution as a first and last resort. My use case probably favours the viewBox solution, which is slightly unusual when your requirement is responsiveness.
Upvotes: 15
Views: 5149
Reputation: 7413
I'd recommend using the following logic:
Then you need to use javascript to adapt your visualization based on the screen size. This blog article which is serious about visualizations' responsiveness.
Oh, and don't forget to debounce your resize event listener.
Upvotes: 7