每个条形堆积条形图D3.js上方的值

时间:2018-10-21 18:02:06

标签: javascript d3.js svg data-visualization visualization

因此,我想在条形图上方显示每个条形的总价值。不幸的是,我似乎无法使其直接位于酒吧上方。 我已经尝试了几件事,但是该值似乎在栏的上方保持静态。有人可以帮我吗?我非常感谢。我已经省略了一些代码,因为它太长了。

这是现在的样子:

StackedBar

var x = d3.scaleBand()
    .rangeRound([0, width])
    .paddingInner(0.2);

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

var color = d3.scaleOrdinal()
    .range(d3.schemeGreys[7]);

var xAxis = d3.axisBottom(x);

var yAxis = d3.axisLeft(y)
    .tickFormat(d3.format(".2s"));

var svg = d3.select("body").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 + ")");

var update = function(data) {

  color.domain(d3.keys(data[0]).filter(function(key) { return key !== "Categories"; }));

  data.forEach(function(d) {
    var y0 = 0;
    d.stores = color.domain().map(function(name) { return {name: name, y0: y0, y1: y0 += +d[name]}; });
    d.total = d.stores[d.stores.length - 1].y1;
  });

  data.sort(function(a, b) { return b.total - a.total; });

  x.domain(data.map(function(d) { return d.Categories; }));
  y.domain([0, d3.max(data, function(d) { return d.total; })]);

  svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call((xAxis)
        .tickSize(0)
        .tickPadding(6));

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

    categories.selectAll("rect")
      .data(function(d) { return d.stores; })
    .enter().append("rect")
      .attr("width", x.bandwidth())
      .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); });

    categories.selectAll("text")
      .data(function(d) { return d.stores; })
    .enter().append("text")
      .attr("y", function(d) { return y((d.y0 + d.y1) / 2); })
      .attr("x", x.bandwidth()/2)
      .attr("text-anchor","middle")
      .attr("alighnment-baseline", "middle")
      .style("fill",'#fff')
      .text(function(d) { return d.y1 - d.y0; });

    categories.append("text")
        .attr("text-anchor", "middle")
        .attr("x", x.bandwidth()/2)
        .attr("y", function(d) { return y((d.y0)); }) 
        .style("fill", "black")
        .text(function(d) { return d.total; });
var Data = [
    {
        "Categories": "Lissabon",
        "1": "34",
        "2": "76",
        "3": "87",
        "4": "54",
        "5": "66",
        "6": "72"
    },

1 个答案:

答案 0 :(得分:1)

您可以使用现有的y比例尺来计算总计的位置,方法与对矩形的上下边缘以及每个文本的处理方式相同。无需使用d.y0d.y1,而需要使用d.total

categories.append("text")
  .attr("text-anchor", "middle")
  .attr("x", x.bandwidth()/2)
  .attr("y", function(d) { return y(d.total); }) // d.total!
  .style("fill", "black")
  .text(function(d) { return d.total; });

这会将文本定位在顶部矩形的顶部,因此,最好在此矩形上添加一些偏移:

categories.append("text")
  .attr("text-anchor", "middle")
  .attr("x", x.bandwidth()/2)
  .attr("y", function(d) { return y(d.total); })
  .attr('dy', '-0.5em') // add 0.5em offset
  .style("fill", "black")
  .text(function(d) { return d.total; });

这是一个有效的示例:

var Data = [
    {
        "Categories": "Lissabon",
        "1": "34",
        "2": "76",
        "3": "87",
        "4": "54",
        "5": "66",
        "6": "72"
    },
    { Categories: "This",
      1: 239, 2: 254, 3: 225, 4: 152, 5: 362, 6: 98
    },
    { Categories: "That",
      1: 457, 2: 234, 3: 83, 4: 327, 5: 88, 6: 99
    },
    { Categories: "The Other",
      1: 132, 2: 286, 3: 222, 4: 150, 5: 363, 6: 95
    }
    ]
var height = 600,
width = 600,
margin = { left: 10, right: 10, top: 20, bottom: 20 }

var x = d3.scaleBand()
    .rangeRound([0, width])
    .paddingInner(0.2);

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

var color = d3.scaleOrdinal()
    .range(d3.schemeGreys[7]);

var xAxis = d3.axisBottom(x);

var yAxis = d3.axisLeft(y)
    .tickFormat(d3.format(".2s"));

var svg = d3.select("body").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 + ")");

var update = function(data) {

  color.domain(d3.keys(data[0]).filter(function(key) { return key !== "Categories"; }));

  data.forEach(function(d) {
    var y0 = 0;
    d.stores = color.domain().map(function(name) { return {name: name, y0: y0, y1: y0 += +d[name]}; });
    d.total = d.stores[d.stores.length - 1].y1;
  });

  data.sort(function(a, b) { return b.total - a.total; });

  x.domain(data.map(function(d) { return d.Categories; }));
  y.domain([0, d3.max(data, function(d) { return d.total; })]);

  svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call((xAxis)
        .tickSize(0)
        .tickPadding(6));

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

    categories.selectAll("rect")
      .data(function(d) { return d.stores; })
    .enter().append("rect")
      .attr("width", x.bandwidth())
      .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); });

    categories.selectAll("text")
      .data(function(d) { return d.stores; })
    .enter().append("text")
      .attr("y", function(d) { return y((d.y0 + d.y1) / 2); })
      .attr("x", x.bandwidth()/2)
      .attr('dy', '0.35em')
      .attr("text-anchor","middle")
      .attr("alighnment-baseline", "middle")
      .style("fill",'#fff')
      .text(function(d) { return d.y1 - d.y0; });

    categories.append("text")
      .attr("text-anchor", "middle")
      .attr("x", x.bandwidth()/2)
      .attr("y", function(d) { return y(d.total); })
      .attr('dy', '-0.5em')
      .style("fill", "black")
      .text(function(d) { return d.total; });
}

update(Data)
<script type="text/javascript" src="http://d3js.org/d3.v5.js"></script>