Question

Example on Plunker.

I have 2 1 issues, when there are 3 or more slices in the pie, it looks like there is a little sliver that is not filled in. The other is if there are less than 3 slices in the pie, it looks all wonky.

Looks like the wonky happens when a slice is over 50% of the pie (StephenH comment below).

This is the bit of code that fills in the slices based on an array $scope.viewData is a simple array, [1,2,3] for example. The $scope.viewDataTotal variable is the sum of the array values, 6 for the shown example array.

    $scope.updateView = function () {
      if ($scope.viewData) {
        var svg = $element.children('svg');
        svg.empty();

        var cX = $element.width() / 2;
        var cY = $element.height() / 2;
        var r = cX;
        if (cY < r) {
          r = cY;
        }
        r -= 5;
        if (r < 0) {
          r = 0;
        }

        var sd = 0;
        var idxColor = 0;
        $scope.viewData.forEach(function(i) {
          var degrees = i / $scope.viewDataTotal * 360;

          var p = '<path d="';
          p += generateWedgeString(cX, cY, sd, sd + degrees, r);
          p += '" fill="';
          p += $scope.colors[idxColor];
          p +='" stroke="none" stroke-width="0" />';

          svg.append(jQuery(p));
          sd += degrees;
          idxColor++;
        });

        $element.html($element.html());
      }
    };

The math bit is in the generateWedgeString function:

var generateWedgeString = function(startX, startY, startAngle, endAngle, radius){
  var x1 = startX + radius * Math.cos(Math.PI * startAngle/180);
  var y1 = startY + radius * Math.sin(Math.PI * startAngle/180);
  var x2 = startX + radius * Math.cos(Math.PI * endAngle/180);
  var y2 = startY + radius * Math.sin(Math.PI * endAngle/180);

  var pathString = "M"+ startX + "," + startY + " L" + x1 + "," + y1 + " A" + radius + "," + radius + " 0 0,1 " + x2 + "," + y2 + " z";

  return pathString;
};

update: Dave's answer works but it introduces other issues. For example You can see the divider between each 1/2 of the slice. Another would be I can't easily do mouse over events.

Was it helpful?

Solution

I believe this will be because you are not setting the large-arc-sweep flag to 1 in your path string when a slice is greater than 50%.

Please see this MDN documentation and search for "large-arc-sweep-flag".

Additionally have a look at the piechart directive I have written here and here that demonstrates how to use it.

Hope this helps.

OTHER TIPS

This isn't ideal, but a kind of hacky work around, is to see if the wedge is more than half of the total, if so, cut the wedge in half, and do it twice with the same color:

if (i > ($scope.viewDataTotal/2)) {
    tmp = true;
    degrees/=2;
 }
 var p = '<path d="';
 p += generateWedgeString(cX, cY, sd, sd+degrees, r);
 p += '" fill="';
 p += $scope.colors[idxColor];
 p +='" stroke="none" stroke-width="0" />';
 if (tmp) {
     sd = sd + degrees;
     p += '<path d="';
     p += generateWedgeString(cX, cY, sd, sd+degrees, r);
     p += '" fill="';
     p += $scope.colors[idxColor];
     p +='" stroke="none" stroke-width="0" />';
     tmp=false;
  }

http://plnkr.co/edit/vuoN94nYqv4uZh4ygdhx?p=preview

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top