What's the best way to make a d3.js visualisation layout responsive?
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:
<svg id="chart" viewBox="0 0 960 500"
preserveAspectRatio="xMidYMid meet">
</svg>
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:
var aspect = width / height,
chart = d3.select('#chart');
d3.select(window)
.on("resize", function() {
var targetWidth = chart.node().getBoundingClientRect().width;
chart.attr("width", targetWidth);
chart.attr("height", targetWidth / aspect);
});
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.
Responsive D3 js chart
Set width=100% and height=100% and viewBox and preserveAspectRatio attributes for your SVG elements.
Following solution will give you direction,
var svg = d3.select('#chart').append("svg")
.attr("width", '100%')
.attr("height", '100%')
.attr('viewBox','0 0 '+Math.min(width,height)+' '+Math.min(width,height))
.attr('preserveAspectRatio','xMinYMin')
.append("g") ;
responsive D3 chart
You can make the chart resize using a combination of viewBox
and preserveAspectRatio
attributes on the SVG element.
See this jsfiddle for the full example: http://jsfiddle.net/BTfmH/12/
var svg = d3.select('.chart-container').append("svg")
.attr("width", '100%')
.attr("height", '100%')
.attr('viewBox','0 0 '+Math.min(width,height)+' '+Math.min(width,height))
.attr('preserveAspectRatio','xMinYMin')
.append("g")
.attr("transform", "translate(" + Math.min(width,height) / 2 + "," + Math.min(width,height) / 2 + ")");
You won't even need a resize
handler with this method.
How to create responsive svg using d3.js
If you add a viewBox to the svg element e.g. viewBox="0 0 960 500" you won't need to resize any children.
Resize svg when window is resized in d3.js
Look for 'responsive SVG' it is pretty simple to make a SVG responsive and you don't have to worry about sizes any more.
Here is how I did it:
d3.select("div#chartId") .append("div") // Container class to make it responsive. .classed("svg-container", true) .append("svg") // Responsive SVG needs these 2 attributes and no width and height attr. .attr("preserveAspectRatio", "xMinYMin meet") .attr("viewBox", "0 0 600 400") // Class to make it responsive. .classed("svg-content-responsive", true) // Fill with a rectangle for visualization. .append("rect") .classed("rect", true) .attr("width", 600) .attr("height", 400);
.svg-container { display: inline-block; position: relative; width: 100%; padding-bottom: 100%; /* aspect ratio */ vertical-align: top; overflow: hidden;}.svg-content-responsive { display: inline-block; position: absolute; top: 10px; left: 0;}
svg .rect { fill: gold; stroke: steelblue; stroke-width: 5px;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="chartId"></div>
Related Topics
Detect Rotation of Android Phone in the Browser with JavaScript
How to Update State.Item[1] in State Using Setstate
Is It Safe to Store a Jwt in Localstorage with Reactjs
Push Method in React Hooks (Usestate)
Change Values in Array When Doing Foreach
Get Average Color of Image via JavaScript
How to Check If a Variable Is an Integer in JavaScript
Fastest Way to Convert JavaScript Nodelist to Array
How to Check If a JavaScript Object Is a Dom Object
Split Large String in N-Size Chunks in JavaScript
Accessing Private Member Variables from Prototype-Defined Functions
JavaScript Filter Array Multiple Conditions
How to Create an Asynchronous Function in JavaScript
Make React Useeffect Hook Not Run on Initial Render
Why How to Use a Function Before It's Defined in JavaScript