简体   繁体   中英

D3js charts reponsive

I am trying to get responsive d3js charts. I have set the width and height as 100% for the chart have a resize function which should reduce the size . In what I have done so far it just manages to reduce the labels on the x-axis but the line chart remains of the same size.Is the way I am trying to make the responsive the correct way or is their a better way with which any d3js chart(bar/pie/line) could be made responsive.

 var margin = { top: 30, right: 20, bottom: 30, left: 50 }; var width = parseInt(d3.select("#chart").style("width")) - margin.left - margin.right, height = parseInt(d3.select("#chart").style("height")) - margin.top - margin.bottom; var x = d3.scale.ordinal() .rangeRoundBands([0, width], .1); var y = d3.scale.linear().range([height, 0]); var xAxis = d3.svg.axis().scale(x) .orient("bottom").ticks(5).tickFormat(function (d) { return d.replace('SEASONAL_', ''); });; var yAxis = d3.svg.axis().scale(y) .orient("left").ticks(5); var valueline = d3.svg.line() .x(function (d) { return x(d.name); }) .y(function (d) { return y(d.count); }); var svg = d3.select("body") .append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); // Get the data var all = [{ "name": "Seasonal Pop", "code": "SEASONAL_POP", "children": [{ "name": "SEASONAL_LYQ1", "code": "SEASONAL_LYQ1", "count": 1200 }, { "name": "SEASONAL_LYQ2", "code": "SEASONAL_LYQ2", "count": 2000 }, { "name": "SEASONAL_LYQ3", "code": "SEASONAL_LYQ3", "count": 1060 }, { "name": "SEASONAL_LYQ4", "code": "SEASONAL_LYQ4", "count": 2300 }, { "name": "SEASONAL_CYQ1", "code": "SEASONAL_CYQ1", "count": 1300 }, { "name": "SEASONAL_CYQ2", "code": "SEASONAL_CYQ2", "count": 3400 }, { "name": "SEASONAL_CYQ3", "code": "SEASONAL_CYQ3", "count": 4500 }, { "name": "SEASONAL_CYQ4", "code": "SEASONAL_CYQ4", "count": 5500 }] }]; var data = all[0].children; data.forEach(function (d) { // d.name = +d.date ; d.count = +d.count; }); // Scale the range of the data x.domain(data.map(function (d) { return d.name; })); y.domain([0, d3.max(data, function (d) { return d.count; })]); svg.append("path") // Add the valueline path. .attr("d", valueline(data)); svg.append("g") // Add the X Axis .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis); svg.append("g") // Add the Y Axis .attr("class", "y axis") .call(yAxis); // Define responsive behavior function resize() { var width = parseInt(d3.select("#chart").style("width")) - margin.left - margin.right, height = parseInt(d3.select("#chart").style("height")) - margin.top - margin.bottom; // Update the range of the scale with new width/height x.range([0, width]); y.range([height, 0]); // Update the axis and text with the new scale svg.select('.x.axis') .attr("transform", "translate(0," + height + ")") .call(xAxis); svg.select('.y.axis') .call(yAxis); // Force D3 to recalculate and update the line svg.selectAll('.line') .attr("d", function(d) { return line(d.count); }); // Update the tick marks xAxis.ticks(Math.max(width/75, 2)); yAxis.ticks(Math.max(height/50, 2)); }; // Call the resize function whenever a resize event occurs d3.select(window).on('resize', resize); // Call the resize function resize(); 
 body { font: 12px Arial; } path { stroke: steelblue; stroke-width: 2; fill: none; } .axis path, .axis line { fill: none; stroke: grey; stroke-width: 1; shape-rendering: crispEdges; } #chart { width: 100%; height: 100%; position: absolute; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> <body><svg id="chart"></svg></body> 

Well your code kinda works. Save that you're dealing with two SVGs. The on the page with id="chart" and this one thats appended.

var svg = d3.select("body")
    .append("svg")

But its not really a D3 issue its more to do with responsive SVGs. Responsive charts have problems scaling. The X & Y axis can become misrepresented.

One approach is to scale the entire Chart/SVG. Forget about listening to window resize events. Just set a viewBox property on your main svg. And set a static width hight thats too the correct ratio of your chat.

var svg = d3.select("#chart")
    .attr("viewBox", "0 0 " + viewWidth + " " + viewHeight)

example

 var margin = { top: 30, right: 20, bottom: 30, left: 50 }; var width = 500 - margin.left - margin.right, height = 240 - margin.top - margin.bottom; var x = d3.scale.ordinal() .rangeRoundBands([0, width], .1); var y = d3.scale.linear().range([height, 0]); var xAxis = d3.svg.axis().scale(x) .orient("bottom").ticks(5).tickFormat(function (d) { return d.replace('SEASONAL_', ''); });; var yAxis = d3.svg.axis().scale(y) .orient("left").ticks(5); var valueline = d3.svg.line() .x(function (d) { return x(d.name); }) .y(function (d) { return y(d.count); }); var viewWidth = width - margin.left - margin.right; var viewHeight = height + margin.top + margin.bottom; var svg = d3.select("#chart") .attr("viewBox", "0 0 " + viewWidth + " " + viewHeight) // Get the data var all = [{ "name": "Seasonal Pop", "code": "SEASONAL_POP", "children": [{ "name": "SEASONAL_LYQ1", "code": "SEASONAL_LYQ1", "count": 1200 }, { "name": "SEASONAL_LYQ2", "code": "SEASONAL_LYQ2", "count": 2000 }, { "name": "SEASONAL_LYQ3", "code": "SEASONAL_LYQ3", "count": 1060 }, { "name": "SEASONAL_LYQ4", "code": "SEASONAL_LYQ4", "count": 2300 }, { "name": "SEASONAL_CYQ1", "code": "SEASONAL_CYQ1", "count": 1300 }, { "name": "SEASONAL_CYQ2", "code": "SEASONAL_CYQ2", "count": 3400 }, { "name": "SEASONAL_CYQ3", "code": "SEASONAL_CYQ3", "count": 4500 }, { "name": "SEASONAL_CYQ4", "code": "SEASONAL_CYQ4", "count": 5500 }] }]; var data = all[0].children; data.forEach(function (d) { // d.name = +d.date ; d.count = +d.count; }); // Scale the range of the data x.domain(data.map(function (d) { return d.name; })); y.domain([0, d3.max(data, function (d) { return d.count; })]); svg.append("path") // Add the valueline path. .attr("d", valueline(data)); svg.append("g") // Add the X Axis .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis); svg.append("g") // Add the Y Axis .attr("class", "y axis") .call(yAxis); 
 body { font: 12px Arial; } path { stroke: steelblue; stroke-width: 2; fill: none; } .axis path, .axis line { fill: none; stroke: grey; stroke-width: 1; shape-rendering: crispEdges; } #chart { width: 100%; height: 100%; position: absolute; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script> <body><svg id="chart"></svg></body> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM