D3 - Getting text on the top of rectangles in Vertical Bar chart

后端 未结 2 1004
囚心锁ツ
囚心锁ツ 2021-01-23 20:27

I am making a vertical bar chart with D3 successfully. I further want the value of frequency to lie on the top of each rectangle. I am able to get the complete structure and rec

相关标签:
2条回答
  • 2021-01-23 20:45

    The problem here is simple: you cannot append a text element inside a rect element.

    The text element will show up when you inspect the DOM, but this doesn't mean that it works, and no text will be actually painted in the SVG.

    So, it should be:

     g.selectAll(".text")
          .data(data)
          .enter()
          .append("text")
          .attr("dy", ".75em")
          .attr("y", function(d) { return y(d.frequency); })
          .attr("x", function(d) { return x(d.letter); })
          .attr("text-anchor", "middle")
          .text(function(d) { return d.frequency; });
    

    Note that I changed

    .text(function(d) { return y(d.frequency); });
    

    which makes no sense, to:

    .text(function(d) { return d.frequency; });
    

    Here is a demo with your code:

    var data = [{
        "letter": "A",
        "frequency": "5.01"
    }, {
        "letter": "B",
        "frequency": "7.80"
    }, {
        "letter": "C",
        "frequency": "15.35"
    }, {
        "letter": "D",
        "frequency": "22.70"
    }, {
        "letter": "E",
        "frequency": "34.25"
    }, {
        "letter": "F",
        "frequency": "10.21"
    }, {
        "letter": "G",
        "frequency": "7.68"
    }, ];
    
    
    //Setting up of our svg with proper calculations 
    var svg = d3.select("body")
        .append("svg").attr("width", 500).attr("height", 300);
    var margin = {
        top: 40,
        right: 20,
        bottom: 40,
        left: 40
    };
    var width = svg.attr("width") - margin.left - margin.right;
    var height = svg.attr("height") - margin.top - margin.bottom;
    
    //Plotting our base area in svg in which chart will be shown 
    var g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
    
    //X and Y scaling 
    var x = d3.scaleBand().rangeRound([0, width]).padding(0.4);
    var y = d3.scaleLinear().rangeRound([height, 0]);
    
    x.domain(data.map(function(d) {
        return d.letter;
    }));
    y.domain([0, d3.max(data, function(d) {
        return +d.frequency;
    })]);
    
    //Final Plotting 
    
    //for x axis 
    g.append("g")
        .call(d3.axisBottom(x))
        .attr("transform", "translate(0," + height + ")");
    
    //for y axis 
    g.append("g")
        .call(d3.axisLeft(y))
        .append("text").attr("transform", "rotate(-90)").attr("text-anchor", "end");
    
    //for rectangles 
    g.selectAll(".bar")
        .data(data)
        .enter()
        .append("rect")
        .attr("class", "bar")
        .attr("x", function(d) {
            return x(d.letter);
        })
        .attr("y", function(d) {
            return y(d.frequency);
        })
        .attr("width", x.bandwidth())
        .attr("height", function(d) {
            return height - y(d.frequency);
        });
    
    g.selectAll(".text")
        .data(data)
        .enter()
        .append("text")
        .attr("dy", ".75em")
        .attr("y", function(d) {
            return y(d.frequency) - 16;
        })
        .attr("x", function(d) {
            return x(d.letter) + x.bandwidth() / 2;
        })
        .attr("text-anchor", "middle")
        .text(function(d) {
            return d.frequency;
        });
    <script src="https://d3js.org/d3.v4.min.js"></script>

    0 讨论(0)
  • 2021-01-23 20:59

    The text element should not be inside the rect element. Just append them to your g element instead.

    0 讨论(0)
提交回复
热议问题