d3.js饼图被截断

时间:2016-04-20 11:35:06

标签: angularjs d3.js

我试图将工作的饼图代码从简单的单个HTML文件复制到角度指令。 使用我的指令加载图表有效,但图表被截断。

代码有点长,所以附上codepen demonstration

JS代码:

var app = angular.module('chartApp', []);

app.controller('SalesController', ['$scope', function($scope){
    $scope.salesData=[
        {label: 'aa',value: 54},
        {label: 'bb',value: 26},
        {label: 'cc',value: 20}
    ];
}]);

app.directive('pieChart', function ($window) {
    return {
        restrict: 'EA',
        template: "<svg></svg>",
        link: function (scope, element, attr, ctrl) {
            // render graph only when data avaliable

                var data = scope[attr.chartData];

                var w = 300,
                    h = 300 ;
                var r = 150;

                var d3 = $window.d3;
                var color = d3.scale.category20();     //builtin range of colors
                var svg = d3.select(element.find('svg')[0]);

                svg.data([data])
                    .append('svg')                 //associate our data with the document
                    .attr("width", w)           //set the width and height of our visualization (these will be attributes of the <svg> tag
                    .attr("height", h)
                    .append("svg:g")
                    //make a group to hold our pie chart
                    .attr("transform", "translate(" + r + "," + r + ")");   //move the center of the pie chart from 0, 0 to radius, radius

                var arc = d3.svg.arc()              //this will create <path> elements for us using arc data
                    .outerRadius(r);

                var pie = d3.layout.pie()           //this will create arc data for us given a list of values
                    .value(function(d) { return d.value; });    //we must tell it out to access the value of each element in our data array

                var arcs = svg.selectAll("g.slice")     //this selects all <g> elements with class slice (there aren't any yet)
                    .data(pie)                          //associate the generated pie data (an array of arcs, each having startAngle, endAngle and value properties)
                    .enter()                            //this will create <g> elements for every "extra" data element that should be associated with a selection. The result is creating a <g> for every object in the data array
                    .append("svg:g")                //create a group to hold each slice (we will have a <path> and a <text> element associated with each slice)
                    .attr("class", "slice");    //allow us to style things in the slices (like text)


                arcs.append("svg:path")
                    .attr("fill", function(d, i) { return color(i); } ) //set the color for each slice to be chosen from the color function defined above
                    .attr("d", arc);                                    //this creates the actual SVG path using the associated data (pie) with the arc drawing function

                arcs.append("svg:text")                                     //add a label to each slice
                    .attr("transform", function(d) {                    //set the label's origin to the center of the arc
                        // we have to make sure to set these before calling arc.centroid
                        d.innerRadius = 0;
                        d.outerRadius = r;
                        return "translate(" + arc.centroid(d) + ")";        //this gives us a pair of coordinates like [50, 50]
                    })
                    .attr("text-anchor", "middle")
                    .style("font-size","20px")//center the text on it's origin
                    .text(function(d, i) { return data[i].label; });        //get the label from our original data array            
        }
    };
});

HTML:

<div ng-app="chartApp" ng-controller="SalesController">
  <h1>Chart</h1>
  <div pie-chart chart-data="salesData"></div>
</div>

我已尝试添加填充和保证金,如here所示,但问题仍然存在。

有什么想法吗?

1 个答案:

答案 0 :(得分:2)

您的代码存在以下问题:

  1. 请勿使用template: <svg></svg>,因为稍后您会在其中插入另一个svg。简单地删除该行,以便将饼图插入当前div中。

  2. 您删除了第一个svg元素后,将选择器从var svg = d3.select(element.find('svg')[0])更改为var svg = d3.select(element[0])

  3. 最后,您需要将svg定义链接起来,以便它将指向已包含已翻译g的对象。现在定义svg。然后,您附加了g元素,稍后您附加了另一个g.slice元素,该元素未放置在第一个g内。

  4. 第3点的变化如下:

    // From 
    var svg = d3.select(element[0]);
    svg.data([data]) ...
    
    // To
    var svg = d3.select(element[0])
        .data([data])
        .append('svg') ...
    

    以下是您codepen的一个分支,其中有一个工作示例。

    祝你好运!