2

First of all, I would like to make it clear that I did go through the following link posted in stackoverflow :

Resize svg when window is resized in d3.js

Following is the link to jsfiddle and code: https://jsfiddle.net/adityap16/d61gtadm/8/

Code-

var data = [
{"mytime": "2015-12-01T11:10:00.000Z", "value": 64},
{"mytime": "2015-12-01T11:15:00.000Z", "value": 67},
{"mytime": "2015-12-01T11:20:00.000Z", "value": 70},
{"mytime": "2015-12-01T11:25:00.000Z", "value": 64},
{"mytime": "2015-12-01T11:30:00.000Z", "value": 72},
{"mytime": "2015-12-01T11:35:00.000Z", "value": 75},
{"mytime": "2015-12-01T11:40:00.000Z", "value": 71},
{"mytime": "2015-12-01T11:45:00.000Z", "value": 80}
];
var parseDate = d3.time.format("%Y-%m-%dT%H:%M:%S.%LZ").parse;

data.forEach(function(d) {
          d.mytime = parseDate(d.mytime);
        });
//var margin = { top: 30, right: 30, bottom: 40, left:50 },
var margin = { top: 30, right: 30, bottom: 40, left:50 },
height = 200,
width = 800;
var color =  "green";
var xaxis_param = "mytime";
var yaxis_param = "value"
var params1 =  {margin:margin,height:height,width:width, color: color, xaxis_param:xaxis_param, yaxis_param :yaxis_param};
draw_graph(data,params1);




function  draw_graph(data,params){


    //Get the margin 
    var xaxis_param = params.xaxis_param;
    var yaxis_param = params.yaxis_param;
    var color_code = params.color;
    var margin = params.margin;
    var height = params.height - margin.top - margin.bottom,
        width = params.width - margin.left - margin.right;

    var x_extent = d3.extent(data, function(d){
        return d[xaxis_param]});
    var y_extent = d3.extent(data, function(d){
        return d[yaxis_param]});

    var x_scale = d3.time.scale()
        .domain(x_extent)
        .range([0,width]);


    var y_scale = d3.scale.linear()
        .domain([0,y_extent[1]])
        .range([height,0]);



    //Line
    var lineGen = d3.svg.line()
        .x(function (d) {
            return x_scale(d[xaxis_param]);
        })
        .y(function (d) {
            return y_scale(d[yaxis_param]);
        });
    var myChart = d3.select('body').append('svg')
                    .attr('class','my-chart')
                    .style('background', '#E7E0CB')
                    .attr('width', width + margin.left + margin.right)
                    .attr('height', height + margin.top + margin.bottom)
                    .append('g')
                    .attr('transform', 'translate('+ margin.left +', '+ margin.top +')');
            myChart
                    .append('svg:path')
                    .datum(data)
                    .attr('class', 'line')
                    .attr("d",lineGen)
                    .attr('stroke', color_code)
                    .attr('stroke-width', 1)
                    .attr('fill', 'none');


    var legend = myChart.append("g")
          .attr("class", "legend")
          .attr("transform", "translate(" + 5 + "," + (height - 25) + ")")

        legend.append("rect")
          .style("fill", color_code)
          .attr("width", 20)
          .attr("height", 20);

        legend.append("text")
          .text(yaxis_param)
          .attr("x", 25)
          .attr("y", 12);

    var vGuideScale = d3.scale.linear()
        .domain([0,y_extent[1]])
        .range([height, 0])

    var vAxis = d3.svg.axis()
        .scale(vGuideScale)
        .orient('left')
        .ticks(5)


    var hAxis = d3.svg.axis()
        .scale(x_scale)
        .orient('bottom')
        .ticks(d3.time.minute, 5);

  myChart.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(hAxis);

  myChart.append("g")
      .attr("class", "y axis")
      .call(vAxis)


}

The top voted solution talks about defining the class and making it responsive in css file. When I try to define it that way the code returns an "undefined width" error. I think this is because the axis and other elements are calculated according to the variable width. The only working solution I have been able to come up with is:

var screenWidth =  window.innerWidth;
screenWidth = screenWidth - 0.5*screenWidth;

But after this, whenever the window would be resized, I would have to call d3.select(window).on('resize', resize); and put my code in the resize() function. I am quiet new to javascript and d3 so I might be missing something in the solution already posted. Thanks.

Ishank
  • 2,860
  • 32
  • 43
Aditya Patel
  • 569
  • 1
  • 10
  • 28
  • I took the top answer from your linked question and applied it to your graph [here](https://jsfiddle.net/d61gtadm/10/) – Mark Apr 03 '16 at 13:07
  • Hi @mark, the jsfiddle is not displaying the complete data. if you would notice its only showing data till 11:35 wheras the data is till 11:45. Thanks! – Aditya Patel Apr 05 '16 at 08:01
  • My bad, the view box size needs to be matched to the initial graph size: https://jsfiddle.net/d61gtadm/11/ – Mark Apr 05 '16 at 17:23
  • Hey thanks @mark. I was able to figure it out but now i am stuck with this problem http://stackoverflow.com/questions/36428423/making-d3-chart-responsive-in-react-app?noredirect=1#comment60473297_36428423 – Aditya Patel Apr 05 '16 at 17:51

1 Answers1

5

I would highly recommend the following blog post on the topic called Building Responsive Visualizations in D3. It gives a great end result, and is fairly elegant taking you from a large graph right the way down to a sparkline.

I don't want to copy/paste huge swathes of code from the article, but to ensure this isn't a link only answer the main steps are:

Listen to the Window resize event:

d3.select(window).on('resize', function() {

});

Grab the height/width of the container

let width = parseInt(d3.select(container).style("width"));
let height= parseInt(d3.select(container).style("height"));

Set the range on any scales and re-render

xAxisScale.range([0, width]);
yAxisScale.range([height, 0]);

d3.select(".x-axis").attr("transform", "translate(" + [0, height] + ")").call(xAxis);
d3.select(".y-axis").call(yAxis);

Hide axis if spark line required

if(width < 500 || height < 500) {
    d3.select(".x-axis").style("display", "none");
    d3.select(".y-axis").style("display", "none");
}

On top of this you can add some extra stuff like the article like begging/ending values on your spark line and also re-sampling your data to a sensible resolution as the number of points vastly exceeds your width.

Ian
  • 33,605
  • 26
  • 118
  • 198
  • Thanks for the reply !. I will try it and let you know. – Aditya Patel Apr 04 '16 at 17:59
  • Hey I am unable to integrate the resize function, can you help me out in the working example. Thanks again! – Aditya Patel Apr 05 '16 at 07:14
  • @AdityaPatel You need to be way more specific. Why can't you integrate it? – Ian Apr 05 '16 at 08:15
  • Thanks for the reply. So if you would notice in my code, i have called a draw_graph function, should i call the resize function inside this function or outside. When i tried placing it inside the function and writing the code for some reason. My graph was still unresponsive . Following is the jsfiddle for it https://jsfiddle.net/adityap16/L1Lq868s/1/ – Aditya Patel Apr 05 '16 at 08:26
  • @AdityaPatel You're jsfiddle is selecting the `#graph` instead of the containing element. Therefore you're reading the existing width/height of the graph. In your `resize` function change the two `parseInt(d3.select("#graph")` to `parseInt(d3.select("body")` and it'll work as expected. – Ian Apr 05 '16 at 08:30
  • Thanks!. It worked , but my x axis shrank too much compared to the line. – Aditya Patel Apr 05 '16 at 08:56
  • @AdityaPatel - strange. It looked fine when I tried modifying the JSFiddle, and additionally it shouldn't be possible for them to be different if their sharing the same x-axis scale. – Ian Apr 05 '16 at 09:12
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/108259/discussion-between-aditya-patel-and-ian). – Aditya Patel Apr 05 '16 at 09:39