iphaaw
iphaaw

Reputation: 7204

Resizing D3 Area Chart

I have a D3 area chart which is being drawn just as I want it. I have tried to make it resize with the window. It resizes correctly horizontally, but vertically it seems to be set based on its original height. This is using Safari 9.0.2. It's difficult to describe what its doing so here are some screenshots:

enter image description here

enter image description here

Here is my code:

<html>
<meta charset="utf-8">
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
<style>

#graph 
{
  width: 100%;
  height: 100%;
  position: absolute;
}
</style>

<body>
<svg id="graph"></svg>

<script>

var width = parseInt(d3.select("#graph").style("width"));
var height = parseInt(d3.select("#graph").style("height"));

var parseDate = d3.time.format("%d-%b-%y").parse;

var xScale = d3.time.scale()
    .range([0, width]);

var yScale = d3.scale.linear()
    .range([height, 0]);

var actual = d3.svg.area()
    .x(function(d) { return xScale(d.date); })
    .y0(height)
    .y1(function(d) { return yScale(d.actual); });

var svg = d3.select("#graph")

function resize() 
{
    width = parseInt(d3.select("#graph").style("width"))
    height = parseInt(d3.select("#graph").style("height"));

    xScale.range([0, width]);
    yScale.range([height, 0]);

    svg.selectAll("#actual")
       .attr("d", actual);
}

d3.select(window).on('resize', resize); 

d3.csv("areachart.csv", function(error, data) 
{
    data.forEach(function(d, i) 
    {
        d.date = parseDate(d.date);
        d.actual = +d.actual;
    });

    xScale.domain(d3.extent(data, function(d) { return d.date; }));
    yScale.domain([0, d3.max(data, function(d) { return d.actual; })]);

    svg.append("path")
        .attr("id", "actual")
        .datum(data)
        .attr('fill', 'red')
        .attr("d", actual);

});

</script>
</body>
</html>

Here is the areachart.csv:

date,actual
1-Jan-16,400
1-Feb-16,500
1-Mar-16,634
1-Apr-16,408
1-May-16,185
1-Jun-16,500
1-Jul-16,467
1-Aug-16,456
1-Sep-16,900
1-Oct-16,108
1-Nov-16,200
1-Dec-16,466

Does anyone know how to fix this please? Thanks. Andrew.

Upvotes: 1

Views: 1153

Answers (2)

iphaaw
iphaaw

Reputation: 7204

Thank you fengshui for your help. I finally got it working. Here is my full answer:

<html>
<meta charset="utf-8">
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
<style>
    #graph 
    {
        width: 100%;
        height: 100%;
        position: absolute;
    }
</style>

<body>
<svg id="graph"></svg>

<script>

var width = parseInt(d3.select("#graph").style("width"));
var height = parseInt(d3.select("#graph").style("height"));

var parseDate = d3.time.format("%d-%b-%y").parse;

var xScale = d3.time.scale()
    .range([0, width]);

var yScale = d3.scale.linear()
    .range([height, 0]);

function actualArea()
{
    var actual = d3.svg.area()
        .x(function(d) { return xScale(d.date); })
        .y0(height)
        .y1(function(d) { return yScale(d.actual); });
    return actual
}

var svg = d3.select("#graph")

function resize() 
{
    width = parseInt(d3.select("#graph").style("width"))
    height = parseInt(d3.select("#graph").style("height"));

    xScale.range([0, width]);
    yScale.range([height, 0]);

    svg.selectAll("#actual")
        .attr("d", actualArea());
}

d3.select(window).on('resize', resize); 

d3.csv("areachart.csv", function(error, data) 
{
    data.forEach(function(d, i) 
    {
        d.date = parseDate(d.date);
        d.actual = +d.actual;
    });

    xScale.domain(d3.extent(data, function(d) { return d.date; }));
    yScale.domain([0, d3.max(data, function(d) { return d.actual; })]);

    svg.append("path")
        .attr("id", "actual")
        .datum(data)
        .attr('fill', 'red')
        .attr("d", actualArea());

});

</script>
</div>
</body>

Upvotes: 0

DevGrowth.Tech
DevGrowth.Tech

Reputation: 1563

While resizing, it seems to be set based on its original height vertically is because the svg area setting is not updated in resize function:

svg.selectAll("#actual")
   .attr("d", actual);

Here, the function used to draw d is still using the initial height:

var actual = d3.svg.area()
.x(function(d) { return xScale(d.date); })
.y0(height) // initial height
.y1(function(d) { return yScale(d.actual); });

Try to include height updating in resize function should work.

Upvotes: 2

Related Questions