简体   繁体   中英

Positioning Text in D3

I am trying my first bar chart in D3 and I am stuck getting the label at the right position in the bar. No matter what i do, I am unable to center the label on the bar. Are there any tricks and tips to do this easily ? My code is as below. I have tried to use the width and height to position but still couldn't make it perfect. I tried using the width of the bar but to no avail. Most posts give a formula but none works in my case. I just want the label sitting right inside the bar at the top. I am at the verge of giving up on D3. It's overwhelming to learn a new language as it is and text positioning is making it million times harder.

function makeBarChart()
  {
    d3.select("#barsvg").remove();
    var filtered_values = justFilter(data_for_bar);
    console.log("length",filtered_values.length)
    var barsvg = d3.select("#barchartdiv")
                 .append('svg')
                 .attr("id",'barsvg')
                 .attr("class","barclass")
                 .attr('width',960)
                 .attr('height',160);

    margin = {top: 20, right: 20, bottom: 30, left: 40}
    width = +barsvg.attr("width") - margin.left - margin.right
    height = +barsvg.attr("height") - margin.top - margin.bottom

    var x = d3.scaleBand().rangeRound([0, width]).padding(0.1)
    var y = d3.scaleLinear().rangeRound([height, 0])

    var g = barsvg.append("g")
          .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    x.domain(filtered_values.map(function(d) { return d.year; }));
    //y.domain([0, d3.max(filtered_values, function(d) { return d.female_lfpr; })]);
    y.domain([0, 100]);

    console.log(x.domain())
    console.log(y.domain())

    g.append("g")
      .attr("class", "axis axis--x")
      .attr("transform", "translate(0," + height + ")")
      .call(d3.axisBottom(x));

    g.append("g")
    .attr("class", "axis axis--y")
    .call(d3.axisLeft(y).ticks(11, ".0f"))
    .append("text")
    .attr("transform", "rotate(-90)")
    .attr("y", 6)
    .attr("dy", "0.9em")
    .attr("text-anchor", "end")
    .text("Female LFPR");  

    function select_axis_label(datum) {
    return d3.select('.axis--x')
        .selectAll('text')
        .filter(function(x) { return x == datum.year; });
    }

    g.selectAll(".bar")
    .data(filtered_values)
    .enter().append("rect")
      .attr("class", "bar")
      .attr("x", function(d) { return x(d.year); })
      .attr("y", function(d) { return y(d.female_lfpr); })
      .attr("width", x.bandwidth())
      .attr("height", function(d) {
        return height - y(d.female_lfpr); })
      //.text(function(d) { return d.female_lfpr; })
        .on('mouseover', function(d) {
          select_axis_label(d).attr('style', "font-weight: bold;");
        })
        .on('mouseout', function(d) {
            select_axis_label(d).attr('style', "font-weight: regular;");
      });

    g.selectAll(".text")
    .data(filtered_values)
    .enter()
    .append("text")
    .attr("class","barlabel")
    .attr("text-anchor", "middle")
    .attr("x", function(d, i) {
      return i * (width / filtered_values.length) + (width / filtered_values.length) / 2;
    })
    .attr("y", function(d) {
      return +height - (+d.female_lfpr + 4);
    })
    .text(function(d) {
        return d.female_lfpr.toFixed(1);
      })
    //.attr("transform", "rotate(-90)")  
    .attr("font-family", "sans-serif")
    .attr("font-size", "11px")
    .attr("fill", "black");
  }

Don't mess with the indices (the second argument). For positioning the texts right in the middle of the bar, you just need the same scale you're using for positioning the rects, half of the bandwidth and text-anchor set to middle (which you already have):

.attr("x", function(d) {
    return x(d.year) + x.bandwidth()/2
})

For the vertical position, use the same y value you're using for the rectangles, with a padding or, alternatively, with dominant-baseline set for text-before-edge :

.attr("y", function(d) {
    return y(d.female_lfpr) + padding;//your padding here 
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM