user994165
user994165

Reputation: 9502

D3 Positioning of Text Labels on Bar Chart

I put together this bar chart (scroll to the bottom right)

based on D3's example of a bar chart with negative values

For some reason, the text labels are showing up behind the rectangles. How can I correct this? Also, I'd like to get the text labels to display over the bars and hopefully it won't be a problem that some bars will be too small for the text.

var margin = {top: 30, right: 10, bottom: 10, left: 10},
    width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

var x = d3.scale.linear()
    .range([0, width])

var y = d3.scale.ordinal()
    .rangeRoundBands([0, height], .2);

var xAxis = d3.svg.axis()
    .scale(x)
    .orient("top");

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

svg.selectAll("text")
    .data(["asdf","DDdf","asdfsa"])
  .enter().append("text").text(function(d) {
        return d;
   }).attr("y", function(d, i) {
        return i * (height / ["asdf","asdf","asdfsa"].length)+30;
   }).attr("x", function(d) {
        return 0; //height - (d * 4);
   }).text(String);


//d3.tsv("data.tsv", type, function(error, data) {
  x.domain(d3.extent(data, function(d) { return d.netdonations_over_population_to_gdppercap_percentage; })).nice();
  y.domain(data.map(function(d) { return d.name; }));

  svg.selectAll(".bar")
      .data(data)
    .enter().append("rect")
      .attr("class", function(d) { return d.netdonations_over_population_to_gdppercap_percentage < 0 ? "bar negative" : "bar positive"; })
      .attr("x", function(d) { return x(Math.min(0, d.netdonations_over_population_to_gdppercap_percentage)); })
      .attr("y", function(d) { return y(d.name); })
      .attr("width", function(d) { return Math.abs(x(d.netdonations_over_population_to_gdppercap_percentage) - x(0)); })
      .attr("height", y.rangeBand());

  svg.append("g")
      .attr("class", "x axis")
      .call(xAxis);

  svg.append("g")
      .attr("class", "y axis")
    .append("line")
      .attr("x1", x(0))
      .attr("x2", x(0))
      .attr("y2", height);
}
//});

function type(d) {
  d.value = +d.netdonations_over_population_to_gdppercap_percentage;
  return d;
}

Upvotes: 2

Views: 5615

Answers (1)

Lars Kotthoff
Lars Kotthoff

Reputation: 109232

As pointed out in the comment, your labels are showing up behind that bars because you are adding them before the bars. To fix this, simply move the code that adds the labels after the code that adds the bars.

To position the labels over the bars, you need to adjust the x and y coordinates you are assigning. In particular, you need to assign the same x coordinate as for the bars, i.e.

.attr("x", function(d) { return x(Math.min(0,
        d.netdonations_over_population_to_gdppercap_percentage)); })

All of this will be much easier if you make the label text part of your original data, i.e. for each element add an attribute "label". Then you can pass the same data to the code that creates the labels, access the other data and set the coordinates correctly.

Upvotes: 3

Related Questions