使用D3.js在矩形上显示文本

11

我正在使用d3.js开发归一化堆叠条形图,并尝试在矩形上附加文本。在浏览器检查时,它已被添加,但是它不可见。我想要像这样的结果:enter image description here

这是我的代码:

var margin = {top: 20, right: 100, bottom: 30, left: 40},
    width = 400 - margin.left - margin.right,
    height = 200 - margin.top - margin.bottom;

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

var y = d3.scale.linear()
    .rangeRound([height, 0]);

var color = d3.scale.ordinal()
    .range(["#404041", "#00adef", "#bbbdc0", "#d1d2d4", "#d3d3d3"]);

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

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

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

d3.json("Nstackedbardata.json", function(error, data) {
  color.domain(d3.keys(data[0]).filter(function(key) { return key !== "State"; }));

  data.forEach(function(d) {
    var y0 = 0;
    d.ages = color.domain().map(function(name) {return {name: name, y0: y0, y1: y0 += +d[name]}; });
    d.ages.forEach(function(d) { d.y0 /= y0; d.y1 /= y0; });
  });

  data.sort(function(a, b) { return b.ages[0].y1 - a.ages[0].y1; });

  x.domain(data.map(function(d) { return d.State; }));


  svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis)
      .style("fill", "#bbbdc0")
      .append("text")
      .attr("class","barChartAxisValue");
    var insertLinebreaks = function (d) {
        var el = d3.select(this);
        var words = d.split(' ');
        el.text('');

        for (var i = 0; i < words.length; i++) {
            var tspan = el.append('tspan').text(words[i]);
            if (i > 0)
                tspan.attr('x', 0).attr('dy', '12');
        }
    };
    svg.selectAll('g.x.axis g text').each(insertLinebreaks);
  svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)
      .style("fill", "#bbbdc0")
      .append("text")
      .attr("class","barChartAxisValue")
      .attr("transform", "rotate(-90)")
      .attr("x",-70)
      .attr("y", -15)
      .attr("dy", ".71em")
      .style("text-anchor", "middle")
      .text("Percentage");

  var state = svg.selectAll(".state")
      .data(data)
    .enter().append("g")
      .attr("class", "state")
      .attr("transform", function(d) { return "translate(" + x(d.State) + ",0)"; });


  var sandeep= state.selectAll("rect")
      .data(function(d) { return d.ages; })
      .enter().append("rect")
      .attr("width", x.rangeBand())
      .attr("y", function(d) { return y(d.y1); })
      .attr("height", function(d) { return y(d.y0) - y(d.y1); })
      .style("fill", function(d) { return color(d.name);})
      .append("text")
      .attr("fill","#fff")
       .style("stroke-width", 1)
      .style({"font-size":"18px","z-index":"999999999"})
      .style("text-anchor", "middle")
      .text(function(d) { return ((d.y1-d.y0)*100).toFixed(0);});


});
2个回答

13

你无法将text元素追加到rect元素中。

相反,你应该将它们作为父级g的单独子元素保留:

  var sandeep= state.selectAll(".data")
      .data(function(d) { return d.ages; })
      .enter();

   sandeep.append("rect")
      .classed('data', true)
      .attr("width", x.rangeBand())
      .attr("y", function(d) { return y(d.y1); })
      .attr("height", function(d) { return y(d.y0) - y(d.y1); })
      .style("fill", function(d) { return color(d.name);});

   sandeep
      .append("text")
      .classed('data', true)
      .attr("y", function(d) { return (y(d.y1) + y(d.y0)) / 2; }) // Center text
      .attr("fill","#fff")
      .style("stroke-width", 1)
      .style({"font-size":"18px","z-index":"999999999"})
      .style("text-anchor", "middle")
      .text(function(d) { return ((d.y1-d.y0)*100).toFixed(0);});

我遇到了相同的问题 https://plnkr.co/edit/cVITU9y19MoEfrIMsVYf?p=preview。尝试了你的解决方案,但它没有起作用。有任何想法我做错了什么吗? - ShaMoh

0

这是对ShaMoh在被接受的答案中提出的问题的回应。我本来想把这个放在他的评论下面,但我还没有被允许。

我知道这已经很老了,ShaMoh可能已经死了,或者已经解决了他的问题,但是对于任何发现这个并想知道他的plnkr代码有什么问题的人:

在这段代码中,他将“bar”定义为一个附加到“serie”的rect元素,其中每个d都是数据中的一个:

var bar = serie.selectAll("rect")
            .data(function (d) {
                return d;
            })
            .enter().append("rect")

然后,稍后他将自己的“文本”附加到“bar”(这是一个'rect'元素):
 bar.append("text")
            .attr("x", function (d) {
                return x(d[1]);
            })
            .attr("dy", "1.35em")
            .text(function (d) { return d; });

所以他最终得到了一个被分类为“serie”的'g'分组元素,其中包含每个.data中的d的'rect'元素,并且每个'rect'都附加了一个'text'元素。

html Layout

他需要做的是将他的“text”元素附加到他称之为“serie”的“g”分组元素上。这样,他的“g”将保存附加到它上面的每个条形切片的'rect',以及附加的'text'元素。文本不会被附加到“rect”上而不显示,而是附加到与'rect'相同的'g'上:
 <g class="serie">
     <rect></rect>
     <rect></rect>
     <text></text>
    </g>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接