Assume I have a histogram script that builds a 960 500 svg graphic. How do I make this responsive so on resize the graphic widths and heights are dynamic?
<script>
var n = 10000, // number of trials
m = 10, // number of random variables
data = [];
// Generate an Irwin-Hall distribution.
for (var i = 0; i < n; i++) {
for (var s = 0, j = 0; j < m; j++) {
s += Math.random();
}
data.push(s);
}
var histogram = d3.layout.histogram()
(data);
var width = 960,
height = 500;
var x = d3.scale.ordinal()
.domain(histogram.map(function(d) { return d.x; }))
.rangeRoundBands([0, width]);
var y = d3.scale.linear()
.domain([0, d3.max(histogram.map(function(d) { return d.y; }))])
.range([0, height]);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
svg.selectAll("rect")
.data(histogram)
.enter().append("rect")
.attr("width", x.rangeBand())
.attr("x", function(d) { return x(d.x); })
.attr("y", function(d) { return height - y(d.y); })
.attr("height", function(d) { return y(d.y); });
svg.append("line")
.attr("x1", 0)
.attr("x2", width)
.attr("y1", height)
.attr("y2", height);
</script>
Full example histogram gist is:
https://gist.github.com/993912
There’s another way to do this that doesn’t require redrawing the graph, and it involves modifying the viewBox and preserveAspectRatio attributes on the
<svg>element:Update 11/24/15: most modern browsers can infer the aspect ratio of SVG elements from the
viewBox, so you may not need to keep the chart’s size up to date. If you need to support older browsers, you can resize your element when the window resizes like so:And the svg contents will be scaled automatically. You can see a working example of this (with some modifications) here: just resize the window or the bottom right pane to see how it reacts.