1

After study this excelent d3.js tutorial, I like to add the bar value on top of each bar! below example code the text not show up!

XYZ.csv

year,value
2011,45
2012,47
2013,52
2014,70
2015,75
2016,78

html file:

<!doctype html>
<html>
<head>
    <style>
        .bar {
            fill: steelblue;
        }
    </style>
    <script src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<svg width="600" height="500"></svg>
<script>
var svg = d3.select("svg"),
            margin = 200,
            width = svg.attr("width") - margin,
            height = svg.attr("height") - margin


var xScale = d3.scaleBand().range([0, width]).padding(0.4),
            yScale = d3.scaleLinear().range([height, 0]);

var g = svg.append("g")
            .attr("transform", "translate(" + 100 + "," + 100 + ")");

    d3.csv("XYZ.csv", function(error, data) {
        if (error) {
            throw error;
        }

        xScale.domain(data.map(function(d) { return d.year; }));
        yScale.domain([0, d3.max(data, function(d) { return d.value; })]);

        g.append("g")
         .attr("transform", "translate(0," + height + ")")
         .call(d3.axisBottom(xScale));

        g.append("g")
         .call(d3.axisLeft(yScale).tickFormat(function(d){
             return "$" + d;
         }).ticks(10));

        g.selectAll(".bar")
         .data(data)
         .enter().append("rect")
         .attr("class", "bar")
         .attr("x", function(d) { return xScale(d.year); })
         .attr("y", function(d) { return yScale(d.value); })
         .attr("width", xScale.bandwidth())
         .attr("height", function(d) { return height - yScale(d.value); })
         .append("text")
         .attr("x", function(d) { return xScale(d.year); })
         .attr("y", function(d) { return yScale(d.value); })
         .attr("text", function(d) { return d.value; })
    });
</script>
</body>
</html>

Below code is added for text on top of each bar:

         .append("text")
         .attr("x", function(d) { return xScale(d.year); })
         .attr("y", function(d) { return yScale(d.value); })
         .attr("text", function(d) { return d.value; })
lucky1928
  • 8,708
  • 10
  • 43
  • 92

1 Answers1

1

It's impossible to append a <text> to a <rect>. Just add the texts separately:

g.selectAll(".bar-title")
  .data(data)
  .enter()
  .append("text")
  .classed('bar-title', true)
  .attr('text-anchor', 'middle')
  .attr("x", d => xScale(d.year) + xScale.bandwidth()/2)
  .attr("y", d => yScale(d.value))
  .text(d => `$${d.value}`);

... or, you can append a <g> element on enter() and then append <text> and <rect> under <g>.

const data = [
{year: 2011, value: 45},
{year: 2012, value: 47},
{year: 2013, value: 52},
{year: 2014, value: 70},
{year: 2015, value: 75},
{year: 2016, value: 78}
];

var svg = d3.select("svg"),
            margin = 200,
            width = svg.attr("width") - margin,
            height = svg.attr("height") - margin


var xScale = d3.scaleBand().range([0, width]).padding(0.4),
            yScale = d3.scaleLinear().range([height, 0]);

var g = svg.append("g")
            .attr("transform", "translate(" + 100 + "," + 100 + ")");


        xScale.domain(data.map(function(d) { return d.year; }));
        yScale.domain([0, d3.max(data, function(d) { return d.value; })]);

        g.append("g")
         .attr("transform", "translate(0," + height + ")")
         .call(d3.axisBottom(xScale));

        g.append("g")
         .call(d3.axisLeft(yScale).tickFormat(function(d){
             return "$" + d;
         }).ticks(10));

        g.selectAll(".bar")
         .data(data)
         .enter().append("rect")
         .attr("class", "bar")
         .attr("x", function(d) { return xScale(d.year); })
         .attr("y", function(d) { return yScale(d.value); })
         .attr("width", xScale.bandwidth())
         .attr("height", function(d) { return height - yScale(d.value); })
         
        g.selectAll(".bar-title")
         .data(data)
         .enter()
         .append("text")
         .classed('bar-title', true)
         .attr('text-anchor', 'middle')
         .attr("x", d => xScale(d.year) + xScale.bandwidth()/2)
         .attr("y", d => yScale(d.value) - 5)
         .text(d => `$${d.value}`);
.bar {
  fill: steelblue;
 }
 
 .bar-title {
   font-family: 'Ubuntu';
 }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.min.js"></script>
<svg width="600" height="500"></svg>
Michael Rovinsky
  • 6,807
  • 7
  • 15
  • 30