user5114994
user5114994

Reputation:

Stacked Vertical Bar Chart Labeling - D3.js

I wanted to add data labels on each boxes in bars but couldn't figure out how to do it. All examples I found on the net was getting data from simple arrays, not an external JSON file like I did.

Here is my code:

<!DOCTYPE html>
<meta charset="utf-8">
<style>

body {
  font: 10px sans-serif;
}

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

.bar {
  fill: steelblue;
}

.x.axis path {
  display: none;
}

</style>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script>

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

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

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

var color = d3.scale.ordinal()
    .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);

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

var yAxis = d3.svg.axis()
    //.scale(y)
    .orient("left")
    .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 + ")");

d3.json("data.json", function(error, data) {
  if (error) throw error;

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

  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.Brand; }));
  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);

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

  brand.selectAll("rect")
      .data(function(d) { return d.stores; })
    .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); });

  var legend = svg.selectAll(".legend")
      .data(color.domain().slice().reverse())
    .enter().append("g")
      .attr("class", "legend")
      .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });

  legend.append("rect")
      .attr("x", width - 18)
      .attr("width", 18)
      .attr("height", 18)
      .style("fill", color);

  legend.append("text")
      .attr("x", width - 24)
      .attr("y", 9)
      .attr("dy", ".35em")
      .style("text-anchor", "end")
      .text(function(d) { return d; });

});

</script>

data.json

[
    {
        "Brand": "A",
        "LAST 3 MONTHS": "22",
        "LAST MONTH": "15",
        "THIS YEAR": "36",
        "ALL STORES": "72"
    },
    {
        "Brand": "B",
        "LAST 3 MONTHS": "10",
        "LAST MONTH": "24",
        "THIS YEAR": "15",
        "ALL STORES": "61"
    },
    {
        "Brand": "C",
        "LAST 3 MONTHS": "10",
        "LAST MONTH": "11",
        "THIS YEAR": "23",
        "ALL STORES": "67"
    },
    {
        "Brand": "D",
        "LAST 3 MONTHS": "10",
        "LAST MONTH": "17",
        "THIS YEAR": "21",
        "ALL STORES": "81"
    },
    {
        "Brand": "E",
        "LAST 3 MONTHS": "10",
        "LAST MONTH": "31",
        "THIS YEAR": "51",
        "ALL STORES": "92"
    },
    {
        "Brand": "F",
        "LAST 3 MONTHS": "10",
        "LAST MONTH": "27",
        "THIS YEAR": "35",
        "ALL STORES": "76"
    },
    {
        "Brand": "G",
        "LAST 3 MONTHS": "10",
        "LAST MONTH": "23",
        "THIS YEAR": "19",
        "ALL STORES": "59"
    },
    {
        "Brand": "H",
        "LAST 3 MONTHS": "32",
        "LAST MONTH": "27",
        "THIS YEAR": "15",
        "ALL STORES": "45"
    }
]

How can I show data labels on each boxes in the bars? (like: 22, 15, 36, 72 on the first bar etc.)

I want a final view on all bars like the first bar on this picture: https://dl.dropboxusercontent.com/u/58490833/Yollanan%20Dosyalar/stackedbar.jpg

Upvotes: 0

Views: 1297

Answers (1)

Amit Rana
Amit Rana

Reputation: 1117

Do the same code as you did for all rectangle .. but you have to either pass original object with it to read value or you can get it from parent node like this

brand.selectAll("text")
  .data(function(d) { return d.stores; })
  .enter().append("text")
  .attr("y", function(d) { return y(d.y1)+10; })
  .attr("x", x.rangeBand()/2)
  .attr("text-anchor","middle")
  .style("fill",'#fff')
  .text(function(d) { return d3.select(this)[0][0].parentNode.__data__[d.name]; });

here is fiddle with solution hope this is what you needed ..

Upvotes: 0

Related Questions