D3 - 甜甜圈或饼图中从标签到圆弧的折线

时间:2016-12-07 11:26:26

标签: javascript html5 d3.js svg charts

我正在做一个简单的圆环图。我按预期提供数据并生成甜甜圈。此外,在远处添加标签。现在,我想在标签中添加直线到圆弧的中心。但是,我没有收到任何错误,我也没有看到任何错误。请帮忙!

SNIPPET:



     //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": "60"
            }, {
              "letter": "B",
              "frequency": "30"
            }, {
              "letter": "C",
              "frequency": "10"
            }];

            //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;
            var radius = 200;

            //Plotting our base area in svg in which chart will be shown 
            var g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

            var pie = d3.pie().sort(null)
              .value(function(d) {return d.frequency;});

            var piedata = pie(data);

            var arc = d3.arc()
              .innerRadius(radius - 100)
              .outerRadius(radius - 50);

            var path = g.selectAll("path")
              .data(piedata)
              .enter().append("path")
              .attr("fill", function() {
                return "hsl(" + Math.random() * 360 + ",100%,50%)";
              })
              .attr("d", arc);

            g.selectAll("text").data(piedata)
              .enter()
              .append("text")
              .attr("text-anchor", "middle")
              .attr("x", function(d) {
                var a = d.startAngle + (d.endAngle - d.startAngle) / 2 - Math.PI / 2;
                d.cx = Math.cos(a) * (radius - 75);
                return d.x = Math.cos(a) * (radius - 20);
              })
              .attr("y", function(d) {
                var a = d.startAngle + (d.endAngle - d.startAngle) / 2 - Math.PI / 2;
                d.cy = Math.sin(a) * (radius - 75);
                return d.y = Math.sin(a) * (radius - 20);
              })
              .text(function(d) {
                return d.data.letter;
              });

              var polyline = g.select(".lines")
                      .selectAll("polyline")
                      .data(pie(data), function(d){ return d.data.letter });

              polyline.enter().append("polyline");



          });

    <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>
      </body>


       
            
&#13;
&#13;
&#13;

参考:

  

http://bl.ocks.org/juan-cb/1984c7f2b446fffeedde

1 个答案:

答案 0 :(得分:2)

查看链接的示例,作者介绍了一个辅助函数来计算弧外的角度,然后使用polyline绘制。窃取他们的实现并将其应用到您的图表看起来像这样:

<!DOCTYPE html>
<html>


<head>

  <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) {

    var $scope = {};

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

    //Data in proper format 
    var data = [{
      "letter": "A",
      "frequency": "60"
    }, {
      "letter": "B",
      "frequency": "30"
    }, {
      "letter": "C",
      "frequency": "10"
    }];

    //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;
    var radius = 200;

    //Plotting our base area in svg in which chart will be shown 
    var g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

    var pie = d3.pie().sort(null)
      .value(function(d) {
        return d.frequency;
      });

    var piedata = pie(data);

    var arc = d3.arc()
      .innerRadius(radius - 100)
      .outerRadius(radius - 50);
      
    var outerArc = d3.arc()
	    .innerRadius(radius * 0.9)
	    .outerRadius(radius * 0.9);

    var path = g.selectAll("path")
      .data(piedata)
      .enter().append("path")
      .attr("fill", function() {
        return "hsl(" + Math.random() * 360 + ",100%,50%)";
      })
      .attr("d", arc);

    g.selectAll("text").data(piedata)
      .enter()
      .append("text")
      .attr("text-anchor", "middle")
      /*
      .attr("x", function(d) {
        var a = d.startAngle + (d.endAngle - d.startAngle) / 2 - Math.PI / 2;
        d.cx = Math.cos(a) * (radius - 75);
        return d.x = Math.cos(a) * (radius - 20);
      })
      .attr("y", function(d) {
        var a = d.startAngle + (d.endAngle - d.startAngle) / 2 - Math.PI / 2;
        d.cy = Math.sin(a) * (radius - 75);
        return d.y = Math.sin(a) * (radius - 20);
      })
      */
      .attr("transform", function(d){
        var pos = outerArc.centroid(d);
        pos[0] = radius * (midAngle(d) < Math.PI ? 1 : -1);
        return "translate("+ pos +")";
      })
      .text(function(d) {
        return d.data.letter;
      });

    function midAngle(d) {
      return d.startAngle + (d.endAngle - d.startAngle) / 2;
    }

    var polyline = g.selectAll("polyline")
      .data(piedata, function(d) {
        return d.data.letter
      })
      .enter()
      .append("polyline")
      .attr("points", function(d) {
        var pos = outerArc.centroid(d);
            pos[0] = radius * 0.95 * (midAngle(d) < Math.PI ? 1 : -1);
            
        return [arc.centroid(d), outerArc.centroid(d), pos];
      })
      .style("fill", "none")
      .style("stroke", "black")
      .style("stroke-width", "2px");

    //});
  </script>
</body>

</html>