Assume we now want to change the size of our chart in order to get a page width chart. We add the following CSS to our main division in order to get the full width:
#bar-chart { width:100%; background-color:grey; }
Here is the result:
Of course, this is not what we expect. Since we fixed the SVG size in the source code, our chart size does not adapt to our division. Let's improve that!
To adapt our chart to the parent division, we need to know its size. The parent
size can be retreived with the style()
or getBoundingClientRect()
functions.
The style function returns the value of a given CSS property. the following line
return the width of the parent division bar-chart
:
var width = d3.select("#bar-chart").style('width');
For example, in my case, it returns 385px
. the problem with this function is
that you have to remove the px
string at the end to get an interger:
var width = d3.select("#bar-chart").style('width');
width = parseInt(width);
The second option is to call the function getBoundingClientRect()
:
var size = d3.select('#bar-chart').node().getBoundingClientRect();
It returns an object containing all the properties of the bounding rectangle, for example:
DOMRect {
x: 8
y: 116.875
width: 385
height: 0
top: 116.875
right: 393
bottom: 116.875
left: 8
}
Select to key width
to get the width of the parent div:
var width = d3.select('#bar-chart').node().getBoundingClientRect().width;
It returns 385
which is an integer.
Once the width is retreived, we can resize our SVG. In the previous example, the width of our chart was twice the height, let's keep this ratio and update our SVG size:
var width = d3.select('#bar-chart').node().getBoundingClientRect().width;
var height = width/2;
// Create our SVG container with grey background
var svg = d3.select("#bar-chart")
.append("svg")
.attr("width", width)
.attr("height", height);
Here is the result:
The SVG is resized, but not the bars.
To solve the previous problem, one solution is to calculate the properties of each element acording to the parent width and height:
// Bind data to chart, and create bars
bars.selectAll('rect')
.data(dataset)
.enter()
.append('rect')
.attr('x', (d,i) => i*(width/dataset.length) )
.attr('y', (d) => height-d*(height/100))
.attr('width', 0.8*(width/dataset.length))
.attr('height', (d) => d*(height/100) );
It works, but it is not the best solution. D3.js provides dedicated tools for resizing charts.