D3 - 甜甜圈或饼图中从标签到圆弧的折线 [英] D3 - Polylines from label to arc in Donut or Pie Chart

查看:154
本文介绍了D3 - 甜甜圈或饼图中从标签到圆弧的折线的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am making a simple donut chart. I am providing data and generating the donut as expected. Also, labels to the same are added at a distant. Now, I want to add lines right from labels to the center of arc. However, I am not getting any error and also I am not seeing any line. Pls help!

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>


       
            

参考:


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


推荐答案

看着在您的链接示例中,作者引入了一个辅助函数来计算弧外的角度,然后使用折线进行绘制。窃取他们的实现并将其应用于您的图表如下所示:

Looking at your linked example, the author introduces a helper function to compute an angle off the arc and then uses a polyline to draw. Stealing their implementation and applying it to your chart looks like this:

<!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>

这篇关于D3 - 甜甜圈或饼图中从标签到圆弧的折线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆