0

I am using d3.js to draw an animated pie chart. The pie chart works fine, but it is not displaying as responsive. The dimensions of the pie chart do not adjust with the variation of the screen size. I tried Bootstrap with d3.js, however the charts could not be rendered as responsive.

Here is the code:

Javascript:

var w = 583,
h = 500,
r = Math.min(w, h) / 2,
data = [{"label":"Yes:", "percentage":yes_percentage, "value":30}, {"label":"No:", "percentage":no_percentage, "value":70}],   // Data with label-value pairs
data2 = data.map(function(d) { return d.value})
color = d3.scale.category20(),
arc = d3.svg.arc().outerRadius(r),
donut = d3.layout.pie();

var vis = d3.select("#chart-1")
    .append("div")
    .classed("svg-container", true) //container class to make it responsive
    .append("svg")  // Place the chart in 'pie-chart-div'
    .attr("preserveAspectRatio", "xMinYMin meet")
    .attr("viewBox", "0 0 600 400")
    .classed("svg-content-responsive", true)
    .data([data])
    .text("hello")
    .attr("width", w)
    .attr("height", h);

var arcs = vis.selectAll("g.arc")
    .data(donut(data2))
  .enter().append("g")
    .attr("class", "arc")
    .attr("transform", "translate(" + r + "," + r + ")");

var paths = arcs.append("path")
    .attr("fill", function(d, i) { return color(i); });

var labels = arcs.append("text")
      .attr("transform", function(d) { d.innerRadius = 140; return "translate(" + arc.centroid(d) + ")"; })
      .attr("dy", ".85em")
      .text(function(d, i) { return data[i].label+"\n"+data[i].percentage; });


paths.transition()
    .ease("bounce")
    .duration(2000)
    .attrTween("d", tweenPie);

paths.transition()
    .ease("elastic")
    .delay(function(d, i) { return 2000 + i * 50; })
    .duration(750)
    .attrTween("d", tweenDonut);

function tweenPie(b) {
  b.innerRadius = 0;
  var i = d3.interpolate({startAngle: 0, endAngle: 0}, b);
  return function(t) {
    return arc(i(t));
  };
}

function tweenDonut(b) {
  b.innerRadius = r * .6;
  var i = d3.interpolate({innerRadius: 0}, b);
  return function(t) {
    return arc(i(t));
  };
}

CSS:

.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;
}
.chart-style {
    float:left;
    margin:68px 0 0 0
}

HTML:

  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="css/bootstrap.min.css">

  <script src="http://d3js.org/d3.v3.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/queue-async/1.0.7/queue.min.js"></script>   
  <script src="js/jquery.min.js"></script>
  <script src="js/bootstrap.min.js"></script>

<div class="container"> <!-- Bootstrap container -->
    <div id="chart-1" class="chart-style"></div>
</div>


Why is the chart not displayed in responsive format ?

1 Answer 1

2

Couple issues here:

1.) First, you are statically sizing your svg element with:

  .attr("width", w)
  .attr("height", h);

This needs to be a percent:

  .attr("width", '100%')
  .attr("height", '100%');

2.) As you walk up the tree from the svg all parent containers must also have percent sized width. <div id="chart-1" does not, so add:

 .chart-style {
   float: left;
   margin: 68px 0 0 0;
   width: 100%;
 }

In addition, you also have a strange .data call on your svg that makes no sense and produces a broken DOM.

Running code:

<!DOCTYPE html>
<html>

  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link  data-semver="3.3.7" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
    <script data-semver="2.2.4" src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
    <script data-semver="3.3.7" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    <script src="http://d3js.org/d3.v3.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/queue-async/1.0.7/queue.min.js"></script>
    <style>
    .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;
    }
    
    .chart-style {
      float: left;
      margin: 68px 0 0 0;
      width: 100%;
    }
  </style>
  </head>

  <body>
    <div class="container">
      <div id="chart-1" class="chart-style"></div>
    </div>
    <script>
    var w = 583,
      h = 500,
      r = Math.min(w, h) / 2,
      data = [{
        "label": "Yes:",
        "percentage": 25,
        "value": 30
      }, {
        "label": "No:",
        "percentage": 75,
        "value": 70
      }], // Data with label-value pairs
      data2 = data.map(function(d) {
        return d.value
      })
    color = d3.scale.category20(),
      arc = d3.svg.arc().outerRadius(r),
      donut = d3.layout.pie();

    var vis = d3.select("#chart-1")
      .append("div")
      .classed("svg-container", true) //container class to make it responsive
      .append("svg") // Place the chart in 'pie-chart-div'
      .attr("preserveAspectRatio", "xMinYMin meet")
      .attr("viewBox", "0 0 600 500")
      .classed("svg-content-responsive", true)
      //.data([data])
      //.text("hello")
      .attr("width", '100%')
      .attr("height", '100%');

    var arcs = vis.selectAll("g.arc")
      .data(donut(data2))
      .enter().append("g")
      .attr("class", "arc")
      .attr("transform", "translate(" + r + "," + r + ")");

    var paths = arcs.append("path")
      .attr("fill", function(d, i) {
        return color(i);
      });

    var labels = arcs.append("text")
      .attr("transform", function(d) {
        d.innerRadius = 140;
        return "translate(" + arc.centroid(d) + ")";
      })
      .attr("dy", ".85em")
      .text(function(d, i) {
        return data[i].label + "\n" + data[i].percentage;
      });


    paths.transition()
      .ease("bounce")
      .duration(2000)
      .attrTween("d", tweenPie);

    paths.transition()
      .ease("elastic")
      .delay(function(d, i) {
        return 2000 + i * 50;
      })
      .duration(750)
      .attrTween("d", tweenDonut);

    function tweenPie(b) {
      b.innerRadius = 0;
      var i = d3.interpolate({
        startAngle: 0,
        endAngle: 0
      }, b);
      return function(t) {
        return arc(i(t));
      };
    }

    function tweenDonut(b) {
      b.innerRadius = r * .6;
      var i = d3.interpolate({
        innerRadius: 0
      }, b);
      return function(t) {
        return arc(i(t));
      };
    }
  </script>
  </body>

</html>

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.