JMags1632
JMags1632

Reputation: 69

Starting point of x-axis in d3.js bar chart is not aligned with the y-intercept

Created a d3.js bar chart based on some examples I've seen online and I've come across a problem. I'd like to align the starting datapoint based on the x-axis with the y-intercept. However, I can't seem to do so correctly even after various changes (changing scale.ordinal to scale.linear, adding transform to y-axis, etc.).

Likewise, I'd like the ending point in the x-axis to be aligned with the last data point. There's like an invisible padding before and after the range of starting and beginning of the datapoints in the chart.

I've consulted this question here as it seems similar to my problem but came up short with my expected results: D3Js Bar Chart Bars Starting Way After beginning of X-Axis

Here's the current code that I have:

var dataUrl = 'https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/GDP-data.json';

// set the dimensions of the canvas
var margin = {
    top: 20,
    right: 20,
    bottom: 70,
    left: 40
  },
  width = 1500 - margin.left - margin.right,
  height = 600 - margin.top - margin.bottom;

// Define the div for the tooltip
var div = d3.select("body").append("div")
  .attr("class", "tooltip")
  .style("opacity", 0);

// set the ranges
var x = d3.scale.ordinal().rangeRoundBands([0, width], 0.01, 1);
var y = d3.scale.linear().range([height, 0]);

// define the axis
var xAxis = d3.svg.axis()
  .scale(x)
  .orient("bottom")
  // Added for the vertical lines (need to remove later)
  .innerTickSize(-height)
  .outerTickSize(0)
  .tickPadding(10);

var yAxis = d3.svg.axis()
  .scale(y)
  .orient("left")
  .ticks(10);

var svg = d3.select(".chart")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

// load the data
d3.json(dataUrl, function(error, data) {
  data.data.forEach(function(d) {
    d.GDP = d[0];
    d.Year = +d[1];
  });

  // scale the range of the data
  x.domain(data.data.map(function(d) {
    return d.GDP;
  }));
  y.domain([0, d3.max(data.data, function(d) {
    return d.Year;
  })]);

  // add axis
  svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis)
    .selectAll("text")
    .style("text-anchor", "end")
    .attr("dx", "-.8em")
    .attr("dy", "-.55em")
    .attr("transform", "rotate(-90)");

  svg.append("g")
    .attr("class", "y axis")
    // .attr("transform", "translate(" + margin.left + ", 0)")
    .call(yAxis)
    .append("text")
    .attr("transform", "rotate(-90)")
    .attr("y", 5)
    .attr("dy", ".71em")
    .style("text-anchor", "end")
    .text("Gross Domestic Product, USA");

  // Add bar chart with tooltip
  svg.selectAll("bar")
    .data(data.data)
    .enter().append("rect")
    .attr("class", "bar")
    .attr("x", function(d) {
      return x(d.GDP);
    })
    .attr("width", x.rangeBand())
    .attr("y", function(d) {
      return y(d.Year);
    })
    .attr("height", function(d) {
      return height - y(d.Year);
    })
    .on("mouseover", function(d) {
      var monthNameFormat = d3.time.format("%b-%Y")
      var gdp_date = monthNameFormat(new Date(d[0]))
      var formatDecimalComma = d3.format(",.2f")
      var curr = formatDecimalComma(d[1])
      div.transition()
        .duration(200)
        .style("opacity", .9);
      div.html(gdp_date + "<br/> $" + curr + " Billion")
        .style("left", (d3.event.pageX) + "px")
        .style("top", (d3.event.pageY - 28) + "px");
    })
    .on("mouseout", function(d) {
      div.transition()
        .duration(500)
        .style("opacity", 0);
    });
});
.chart rect {
  fill: steelblue;
}

.chart text {
  fill: black;
  font: 10px sans-serif;
  text-anchor: middle;
}

bar {
  fill: steelblue;
}

.bar:hover {
  fill: red;
}

.axis {
  font: 10px sans-serif;
}

.axis path,
.axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}

div.tooltip {
  position: absolute;
  text-align: center;
  width: 130px;
  height: 30px;
  padding: 2px;
  font: 12px sans-serif;
  background: lightsteelblue;
  border: 0px;
  border-radius: 8px;
  pointer-events: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<!-- Source: https://bost.ocks.org/mike/bar/3/ -->
<div id="chart" align="center">
  <svg class="chart"></svg>
</div>

Upvotes: 1

Views: 2366

Answers (1)

Gerardo Furtado
Gerardo Furtado

Reputation: 102198

Change rangeRoundBands to rangeBands and remove all the paddings:

var x = d3.scale.ordinal().rangeBands([0, width]);

Here is your code with that change:

var dataUrl = 'https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/GDP-data.json';

// set the dimensions of the canvas
var margin = {
    top: 20,
    right: 20,
    bottom: 70,
    left: 40
  },
  width = 1500 - margin.left - margin.right,
  height = 600 - margin.top - margin.bottom;

// Define the div for the tooltip
var div = d3.select("body").append("div")
  .attr("class", "tooltip")
  .style("opacity", 0);

// set the ranges
var x = d3.scale.ordinal().rangeBands([0, width]);
var y = d3.scale.linear().range([height, 0]);

// define the axis
var xAxis = d3.svg.axis()
  .scale(x)
  .orient("bottom")
  // Added for the vertical lines (need to remove later)
  .innerTickSize(-height)
  .outerTickSize(0)
  .tickPadding(10);

var yAxis = d3.svg.axis()
  .scale(y)
  .orient("left")
  .ticks(10);

var svg = d3.select(".chart")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

// load the data
d3.json(dataUrl, function(error, data) {
  data.data.forEach(function(d) {
    d.GDP = d[0];
    d.Year = +d[1];
  });

  // scale the range of the data
  x.domain(data.data.map(function(d) {
    return d.GDP;
  }));
  y.domain([0, d3.max(data.data, function(d) {
    return d.Year;
  })]);

  // add axis
  svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis)
    .selectAll("text")
    .style("text-anchor", "end")
    .attr("dx", "-.8em")
    .attr("dy", "-.55em")
    .attr("transform", "rotate(-90)");

  svg.append("g")
    .attr("class", "y axis")
    // .attr("transform", "translate(" + margin.left + ", 0)")
    .call(yAxis)
    .append("text")
    .attr("transform", "rotate(-90)")
    .attr("y", 5)
    .attr("dy", ".71em")
    .style("text-anchor", "end")
    .text("Gross Domestic Product, USA");

  // Add bar chart with tooltip
  svg.selectAll("bar")
    .data(data.data)
    .enter().append("rect")
    .attr("class", "bar")
    .attr("x", function(d) {
      return x(d.GDP);
    })
    .attr("width", x.rangeBand())
    .attr("y", function(d) {
      return y(d.Year);
    })
    .attr("height", function(d) {
      return height - y(d.Year);
    })
    .on("mouseover", function(d) {
      var monthNameFormat = d3.time.format("%b-%Y")
      var gdp_date = monthNameFormat(new Date(d[0]))
      var formatDecimalComma = d3.format(",.2f")
      var curr = formatDecimalComma(d[1])
      div.transition()
        .duration(200)
        .style("opacity", .9);
      div.html(gdp_date + "<br/> $" + curr + " Billion")
        .style("left", (d3.event.pageX) + "px")
        .style("top", (d3.event.pageY - 28) + "px");
    })
    .on("mouseout", function(d) {
      div.transition()
        .duration(500)
        .style("opacity", 0);
    });
});
.chart rect {
  fill: steelblue;
}

.chart text {
  fill: black;
  font: 10px sans-serif;
  text-anchor: middle;
}

bar {
  fill: steelblue;
}

.bar:hover {
  fill: red;
}

.axis {
  font: 10px sans-serif;
}

.axis path,
.axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}

div.tooltip {
  position: absolute;
  text-align: center;
  width: 130px;
  height: 30px;
  padding: 2px;
  font: 12px sans-serif;
  background: lightsteelblue;
  border: 0px;
  border-radius: 8px;
  pointer-events: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<!-- Source: https://bost.ocks.org/mike/bar/3/ -->
<div id="chart" align="center">
  <svg class="chart"></svg>
</div>

Upvotes: 1

Related Questions