title: Pie Chart Labels with D3.js and AngularJS
body: <p>I'm new to D3. Trying to show "outside" labels with lines, in D3, similar to Bostock's pie chart here  <a href="http://bl.ocks.org/dbuezas/9306799" rel="nofollow">http://bl.ocks.org/dbuezas/9306799</a> I can't get the labels or lines to show up like Bostock's pie.  The pie is working well though!  Any help with my code, mainly the directive, would be appreciated!</p>
  
  <p>HTML:</p>
  
  <pre><code>&lt;div ng-controller="myControl"&gt;
     &lt;d3-pie-dir data="d3Data"&gt;&lt;/d3-pie-dir&gt;
  &lt;/div&gt;
  </code></pre>
  
  <p>CSS: </p>
  
  <pre><code>path.slice{
     stroke-width:2px;
  }
  
  polyline{
    opacity: .3;
    stroke: black;
    stroke-width: 2px;
    fill: none;
  }
  </code></pre>
  
  <p>Controller:</p>
  
  <pre><code>inAng.controller('myControl', function ( $scope, $http ) {
    var stack = [];
  $http.get("/getAPIData").
      success(function (data, status, headers, config) {
  
       // formatting for easier D3 consumption
        for(var i in data)
          stack.push(data [i]);
  
      $scope.d3Data = stack;  
      // looks something like $scope.d3Data = [{ name: 'Bill', score: 25}, { name: 'Pete', score: 50}]
      }).
      error(function (data, status, headers, config) {
        $scope.stack = 'Error!';
      });
  
  });
  </code></pre>
  
  <p>And the problem is in the directive:</p>
  
  <pre><code>inAng.directive('d3PieDir', function () {
      return {
          restrict: 'E',
          scope: {
              data: '='
          },
          link: function (scope, element, attrs) {
              scope.$watch('data', function(values) {
                  if(values) { 
                      console.log('values from directive: ', values);                 
  
                      var width = 960,
                      height = 500,
                      radius = Math.min(width, height) / 2;
  
                      var color = d3.scale.ordinal()
                          .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
  
                      var arc = d3.svg.arc()
                          .outerRadius(radius - 10)
                          .innerRadius(0);
  
                      var pie = d3.layout.pie()
                          .sort(null)
                          .value(function(d) { 
                              return d.score; 
                          });
  
                      var svg = d3.select("body").append("svg")
                          .attr("width", width)
                          .attr("height", height)
                          .append("g")
                          .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
  
  
                          values.forEach(function(d) {
                              d.score = +d.score;
                          });
  
                          var g = svg.selectAll(".arc")
                              .data(pie(values))
                              .enter().append("g")
                              .attr("class", "arc");
  
                          g.append("path")
                              .attr("d", arc)
                              .style("fill", function(d) { return color(d.data.name); });
  
  // **** Below is where it stops working! ****
  
  var key = function(d){ return d.data.name; };                           
  
  
  /* ------- PIE SLICES -------*/
  var slice = svg.select(".slices").selectAll("path.slice")
      .data(pie(values), key);
  
  slice.enter()
      .insert("path")
      .style("fill", function(d) { return color(d.data.name); })
      .attr("class", "slice");
  
  slice       
      .transition().duration(1000)
      .attrTween("d", function(d) {
          this._current = this._current || d;
          var interpolate = d3.interpolate(this._current, d);
          this._current = interpolate(0);
          return function(t) {
              return arc(interpolate(t));
          };
      })
  
  slice.exit()
      .remove();
  
  /* ------- TEXT LABELS -------*/
  
  var text = svg.select(".labels").selectAll("text")
      .data(pie(values), key);
  
  text.enter()
      .append("text")
      .attr("dy", ".35em")
      .text(function(d) {
          return d.data.name;
      });
  
  function midAngle(d){
      return d.startAngle + (d.endAngle - d.startAngle)/2;
  }
  
  text.transition().duration(1000)
      .attrTween("transform", function(d) {
          this._current = this._current || d;
          var interpolate = d3.interpolate(this._current, d);
          this._current = interpolate(0);
          return function(t) {
              var d2 = interpolate(t);
              var pos = outerArc.centroid(d2);
              pos[0] = radius * (midAngle(d2) &lt; Math.PI ? 1 : -1);
              return "translate("+ pos +")";
          };
      })
      .styleTween("text-anchor", function(d){
          this._current = this._current || d;
          var interpolate = d3.interpolate(this._current, d);
          this._current = interpolate(0);
          return function(t) {
              var d2 = interpolate(t);
              return midAngle(d2) &lt; Math.PI ? "start":"end";
          };
      });
  
  text.exit()
      .remove();
  
  /* ------- SLICE TO TEXT POLYLINES -------*/
  
  var polyline = svg.select(".lines").selectAll("polyline")
      .data(pie(values), key);
  
  polyline.enter()
      .append("polyline");
  
  polyline.transition().duration(1000)
      .attrTween("points", function(d){
          this._current = this._current || d;
          var interpolate = d3.interpolate(this._current, d);
          this._current = interpolate(0);
          return function(t) {
              var d2 = interpolate(t);
              var pos = outerArc.centroid(d2);
              pos[0] = radius * 0.95 * (midAngle(d2) &lt; Math.PI ? 1 : -1);
              return [arc.centroid(d2), outerArc.centroid(d2), pos];
          };          
      });
  
  polyline.exit()
      .remove();
  
                  }
              })}
  
  }});
  </code></pre>