【问题标题】:D3 - Getting text on the top of rectangles in Vertical Bar chartD3 - 在垂直条形图中的矩形顶部获取文本
【发布时间】:2017-04-13 05:38:54
【问题描述】:

我正在使用 D3 成功制作垂直条形图。我还希望频率值位于每个矩形的顶部。我能够得到完整的结构和矩形。但是,我看不到我的价值观存在于酒吧之上。有人可以帮忙吗?

片段:

<html>

<head>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.12/angular.min.js"></script> 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js"></script>

</head> 

<body ng-app="myApp" ng-controller="myCtrl"> 

    <svg></svg>

    <script>

        //module declaration 
        var app = angular.module('myApp',[]);

        //Controller declaration
        app.controller('myCtrl',function($scope){

            $scope.svgWidth = 800;//svg Width
            $scope.svgHeight = 500;//svg Height 

            //Data in proper format 
            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"},
            ];

                //removing prior svg elements ie clean up svg 
                d3.select('svg').selectAll("*").remove();

                //resetting svg height and width in current svg 
                d3.select("svg").attr("width", $scope.svgWidth).attr("height", $scope.svgHeight);

                //Setting up of our svg with proper calculations 
                var svg = d3.select("svg");
                var margin = {top: 20, right: 20, bottom: 30, 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(".bar")
                .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 y(d.frequency); });


        });

    </script> 

</body> 

</html> 

结果:

DOM:

可以看出,我的文本是在每个矩形的 dom 中添加的,但看不到。请帮助他们在矩形顶部被看到。

【问题讨论】:

    标签: javascript angularjs d3.js svg bar-chart


    【解决方案1】:

    这里的问题很简单:您不能rect 元素中附加text 元素。

    text 元素会在您检查 DOM 时出现,但这并不意味着它可以工作,并且不会在 SVG 中实际绘制任何文本。

    所以,应该是:

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

    注意我改了

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

    这毫无意义,要:

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

    这是一个包含您的代码的演示:

    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;
        });
    &lt;script src="https://d3js.org/d3.v4.min.js"&gt;&lt;/script&gt;

    【讨论】:

    • 它运行良好。还有一件事,在这个例子中我们如何将文本旋转为 (-90)deg ?
    【解决方案2】:

    文本元素不应位于 rect 元素内。只需将它们附加到您的 g 元素即可。

    【讨论】:

      猜你喜欢
      • 2021-11-20
      • 1970-01-01
      • 1970-01-01
      • 2018-12-12
      • 2020-08-05
      • 2016-07-04
      • 1970-01-01
      • 1970-01-01
      • 2020-09-14
      相关资源
      最近更新 更多