0

I have made a parallel coordinates chart, now I want to make it responsive.
For the purpose of testing responsiveness, I thought to first make this example by Mike Bostock responsive.

The problem I am facing is that if I put the "svg" directly inside "body" tag, it works perfectly. But when I place the "svg" inside some divs, the chart gets cropped when the window is resized. Also, the height of the svg is mentioned as 70%, if I make it 80% then the chart gets cropped without any resize. I know there is another option which is to use viewBox and preserveAspectRatio, but I used this approach as it was easy to understand, for me or any other person reading my code. Here is the approach:

 d3.csv("data.csv",function(data){
  ....
 function resize(){
    width = parseInt(d3.select("#mychart").style("width")) - margin.left - margin.right,
      height = parseInt(d3.select("#mychart").style("height")) - margin.top - margin.bottom;

      x.rangePoints([0, width], 1);

      svg.select("#mychart")
          .attr("width", width + margin.left + margin.right)
          .attr("height", height + margin.top + margin.bottom);

      x.domain(dimensions = d3.keys(cars[0]).filter(function(d) {
            return d != "name" && (y[d] = d3.scale.linear()
                .domain(d3.extent(cars, function(p) { return +p[d]; }))
                .range([height, 0]));
          }));

      svg.selectAll(".line").attr("d", path);

      g = svg.selectAll(".dimension")
          .attr("transform", function(d) { return "translate(" + x(d) + ")"; });

      g.selectAll(".axis")
          .each(function(d) {d3.select(this).call(axis.scale(y[d])); })
        .append("text")
          .style("text-anchor", "middle")
          .attr("y", -9)
          .text(function(d) { return d; });
  }
  d3.select(window).on('resize', resize);
  resize();
});

Here is the plunker link for the full code. Can anybody please point out whats wrong with the code?

itzcutiesush
  • 89
  • 1
  • 9
  • The chart doesn't get cropped for me when resizing in the plunker you linked. I am using Firefox 44. – LeartS Nov 21 '15 at 10:00
  • Sorry for not mentioning before but the chart gets cropped on resize. Also, the height of svg is mentioned as 70%, if I increase it to 80%, the chart gets cropped without any resize. – itzcutiesush Nov 21 '15 at 10:13

1 Answers1

0

This is more about understanding CSS.

Specifically, you can give your <svg> element a height of 100%, and then set the size of the containing element.

See my example.

Here, the <svg> always has a height of 100%, and the <div> containing the <svg> has a percentage height, which is in turn relative to the .container-fluid container, which has an absolute height (in viewport units).

Also, check out this answer:

If you want to make the div height a percentage of the viewport height, every ancestor of the div, including and , have to have height: 100%, so there is a chain of explicit percentage heights down to the div.

Alternatively, all modern browsers and IE>=9 support new CSS units relative to viewport height (vh) and viewport width (vw):

And this answer:

To cause your SVG to fill an HTML element, put the CSS attribute position:relative (or position:absolute or position:fixed if appropriate) on your wrapper, and then [...] set the CSS attribute position:absolute on your <svg> element to cause it to sit inside and fill your div. (If necessary, also apply left:0; top:0; width:100%; height:100%.)

You can (as I did) use viewport units to set the height of the containing div.

Alternatively, you could try using the flexbox property to position your .row elements.


Also, your resize() function can be greatly simplified. It needs to do three things:

  1. Update the range of your scales
  2. Update any attributes that use those scales
  3. Call your axis function
  function resize() {
    width = parseInt(d3.select("#mychart").style("width")) - margin.left - margin.right,
    height = parseInt(d3.select("#mychart").style("height")) - margin.top - margin.bottom;

    x.rangePoints([0, width], 1);

    d3.values(y).forEach(function(scale) {
      scale.range([height, 0])
    })

    svg.selectAll(".line").attr("d", path);

    g = svg.selectAll(".dimension")
      .attr("transform", function(d) {
        return "translate(" + x(d) + ")";
      });

    g.selectAll(".axis").call(axis.scale(y[d]))
  }
Community
  • 1
  • 1
Paul Murray
  • 1,002
  • 1
  • 10
  • 24
  • Thanks for your reply. I went through your example. Can you explain me how giving height as "vh" is useful? When I make the window smaller, the chart does gets chopped with height as 70vh. If I change it to 50vh, it gets chopped if I further reduce the window size. So, is it like we have to set a viewport height by trial & error? And also, what if I want a minimum height & width for the svg? – itzcutiesush Nov 23 '15 at 05:58