19

I have a parent container (div.barChartContainer) whose height and width are calculated from the viewport, ex: width: calc(100vh - 200px). The SVG container is appended to the div.barChartContainer element.

I am struggling with how to get the SVG element to be 100% width and height of its parent element, hoping I could get some help. For now I have static pixel amounts (where it currently renders properly, but is non responsive).

Thanks!

  var margin = {top: 20, right: 20, bottom: 30, left: 80},
          width = 960 - margin.left - margin.right,
          height = 500 - margin.top - margin.bottom;          
          // set the ranges
          var y = d3.scaleBand()
          .range([height, 0])
          .padding(0.4);
          var x = d3.scaleLinear()
          .range([0, width]);          
          var svg = d3.select(".barChartContainer").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 + ")");
Ron I
  • 4,090
  • 8
  • 33
  • 64

2 Answers2

24

The solution was to comment out/remove the width and height attribute values and instead add the following two lines:

//- .attr("width", width + margin.left + margin.right)
//- .attr("height", height + margin.top + margin.bottom)
.attr("preserveAspectRatio", "xMinYMin meet")
.attr("viewBox", "0 0 960 500")
Ron I
  • 4,090
  • 8
  • 33
  • 64
  • Just a warning ; `viewBox` attribute is case-sensitive! Notice it is should be `camelCase`. Using an attribute `viewbox` will not work. Also crosslinking other similar questions/answers: https://stackoverflow.com/questions/9400615/whats-the-best-way-to-make-a-d3-js-visualisation-layout-responsive https://stackoverflow.com/questions/11942500/how-to-make-force-layout-graph-in-d3-js-responsive-to-screen-browser-size – Nate Anderson Sep 26 '19 at 22:22
  • https://chartio.com/resources/tutorials/how-to-resize-an-svg-when-the-window-is-resized-in-d3-js/ – Dendi Handian Nov 06 '20 at 07:51
2

Check the svg is drawn with parent height and width.

Ref: https://bl.ocks.org/curran/3a68b0c81991e2e94b19

var parentDiv = document.getElementById("parentDiv");
var svg = d3.select(parentDiv).append("svg");

function redraw(show) {

  // Extract the width and height that was computed by CSS.
  var width = parentDiv.clientWidth;
  var height = parentDiv.clientHeight;
  // Use the extracted size to set the size of an SVG element.
  svg
    .attr("width", width)
    .attr("height", height);
  if (show === false) {
    svg.style('visibility', 'hidden');
  } else {
    svg.style('visibility', 'visible');
  }

  svg.attr("style", "outline: thin solid red;")
    .append("circle")
    .attr("cx", 30)
    .attr("cy", 30)
    .attr("r", 20);
}

// Draw for the first time to initialize.
redraw(false);

// Redraw after sometime
setTimeout(redraw, 1000);
#parentDiv {
  height: calc(100vh - 100px); /** output container is small for display */ 
  width: calc(100vw - 100px);
  display: block;
  border: 1px solid red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.10/d3.min.js"></script>
<div id="parentDiv"></div>
Priya
  • 1,522
  • 1
  • 14
  • 31
  • @duhaime , its not at all redrawing as its just setting visibility and if its already trie, it wont impact. and its doing twice only i.e. fist hidden, then visible. I have written `setTimeout` not `setInterval` – Priya Jul 09 '21 at 05:49
  • Oh you are 100% correct! Mea culpa, I somehow read `setInterval` – duhaime Jul 09 '21 at 14:05