2016-04-18 4 views
1

Ich versuche, ein Kreisdiagramm von einem JSON-Objekt anzuzeigen.Wie D3 Chart mit Direktive anzeigen?

Wenn ich mit diesem Objekt versuchen, funktioniert es:

[{ 
    "id": "id1", 
    "name": "the name 1", 
    "values": [{ 
    "age": "One", 
    "population": 5 
    }, { 
    "age": "Two", 
    "population": 2 
    }, { 
    "age": "Three", 
    "population": 9 
    }, { 
    "age": "Four", 
    "population": 7 
    }, { 
    "age": "Five", 
    "population": 4 
    }, { 
    "age": "Six", 
    "population": 3 
    }, { 
    "age": "Seven", 
    "population": 9 
    }] 
}] 

aber nur mit diesem:

[{ 
    "age": "One", 
    "population": 5 
}, { 
    "age": "Two", 
    "population": 2 
}, { 
    "age": "Three", 
    "population": 9 
}, { 
    "age": "Four", 
    "population": 7 
}, { 
    "age": "Five", 
    "population": 4 
}, { 
    "age": "Six", 
    "population": 3 
}, { 
    "age": "Seven", 
    "population": 9 
}] 

Dies ist mein Code:

var app = angular.module("d3Test", ['d3Test.directives']); 
 

 

 

 
angular.module('d3Test.directives', []) 
 

 

 

 
.controller('IndicatorsCtrl', function($scope, Indicators) { 
 
     $scope.datas = '[{ "age": "One", "population": 5 },{ "age": "Two", "population": 2 }]'; 
 

 

 
     .factory('Indicators', function($resource) { 
 
     return $resource('datas.json'); 
 
     }) 
 

 
     angular.module('d3Test.directives', []). 
 
directive('graph', function() { 
 
\t return { 
 
\t \t restrict: 'E', 
 
\t \t scope: { 
 
\t \t \t values: '=' 
 
\t \t }, 
 
\t \t link: function (scope, element, attrs) { 
 
\t \t \t scope.$watch('values', function(values) { 
 
\t \t \t \t if(values) { 
 
\t \t \t \t \t console.log('values from directive: ', values); 
 
\t \t \t \t \t 
 
\t \t \t \t \t var width = 960, 
 
\t \t \t \t \t height = 500, 
 
\t \t \t \t \t radius = Math.min(width, height)/2; 
 
\t \t \t \t \t 
 
\t \t \t \t \t var color = d3.scale.ordinal() 
 
\t \t \t \t \t \t .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]); 
 
\t \t \t \t \t 
 
\t \t \t \t \t var arc = d3.svg.arc() 
 
\t \t \t \t \t \t .outerRadius(radius - 10) 
 
\t \t \t \t \t \t .innerRadius(0); 
 
\t \t \t \t \t 
 
\t \t \t \t \t var pie = d3.layout.pie() 
 
\t \t \t \t \t \t .sort(null) 
 
\t \t \t \t \t \t .value(function(d) { 
 
\t \t \t \t \t \t \t return d.population; 
 
\t \t \t \t \t \t }); 
 
\t \t \t \t \t 
 
\t \t \t \t \t var svg = d3.select("body").append("svg") 
 
\t \t \t \t \t \t .attr("width", width) 
 
\t \t \t \t \t \t .attr("height", height) 
 
\t \t \t \t \t \t .append("g") 
 
\t \t \t \t \t \t .attr("transform", "translate(" + width/2 + "," + height/2 + ")"); 
 
\t \t \t \t \t 
 
\t \t \t \t \t 
 
\t \t \t \t \t 
 
\t \t \t \t \t \t values.forEach(function(d) { 
 
\t \t \t \t \t \t \t d.population = +d.population; 
 
\t \t \t \t \t \t }); 
 
\t \t \t \t \t \t 
 
\t \t \t \t \t \t var g = svg.selectAll(".arc") 
 
\t \t \t \t \t \t \t .data(pie(values)) 
 
\t \t \t \t \t \t \t .enter().append("g") 
 
\t \t \t \t \t \t \t .attr("class", "arc"); 
 
\t \t \t \t \t \t 
 
\t \t \t \t \t \t g.append("path") 
 
\t \t \t \t \t \t \t .attr("d", arc) 
 
\t \t \t \t \t \t \t .style("fill", function(d) { return color(d.data.age); }); 
 
\t \t \t \t \t \t 
 
\t \t \t \t \t \t g.append("text") 
 
\t \t \t \t \t \t \t .attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; }) 
 
\t \t \t \t \t \t \t .attr("dy", ".35em") 
 
\t \t \t \t \t \t \t .style("text-anchor", "middle") 
 
\t \t \t \t \t \t \t .text(function(d) { return d.data.age; }); 
 

 
\t \t \t \t } 
 
\t \t \t }) 
 
\t \t } 
 
\t } 
 
});
<!DOCTYPE html> 
 
<html> 
 

 
<head> 
 
    <script data-require="[email protected]*" data-semver="1.0.7" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js"></script> 
 
    <script data-require="[email protected]" data-semver="1.0.7" src="http://code.angularjs.org/1.0.7/angular-resource.min.js"></script> 
 
    <script data-require="[email protected]*" data-semver="3.2.2" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.2.2/d3.v3.min.js"></script> 
 
    <script src="script.js"></script> 
 
</head> 
 

 
<body ng-app="d3Test"> 
 
    <div ng-controller="IndicatorsCtrl"> 
 

 

 
    <p>datas: {{datas}}</p> 
 
    <p>values: {{datas[0].values}}</p> 
 

 
    </div> 
 

 

 

 
</body> 
 

 
</html>

Antwort

0

Ich denke, Sie rufen wahrscheinlich Ihre <graph />-Direktive falsch (entweder das oder ändern Sie Ihre Richtlinie zu 2-Wege-Bindung compositeObject und rufen Sie dann compositeObject.values); Die Art und Weise wie Ihre Direktive geschrieben wird, sollten Sie die Werte übergeben, nicht das Objekt.

Auch wenn Sie Ihre <graph /> automatisch aktualisiert werden, wenn eine der Daten ändert Sie irgendeine Art von tief $watch tun müssen, um (mit einem Wert von true als drittes Argument). Ich habe diese d3-Charts für ein Dashboard in Angular selbst eine Weile zurück gewickelt ... although consider using a library for your charts.

Hier ist ein ein Beispiel aus dem Code arbeiten (ich habe 1.0.8 statt 1.0.7, weil Ihre Links https waren):

https://plnkr.co/edit/KTLMV2ObafZAkLr11Gxy?p=preview

app.js

var app = angular.module("d3Test", ['ngResource']) 
.controller('IndicatorsCtrl', function($scope, Indicators) { 
    $scope.datas = [{ 
    "age": "One", 
    "population": 5 
    }, { 
    "age": "Two", 
    "population": 2 
    }]; 
}) 
.factory('Indicators', function($resource) { 
    return $resource('datas.json'); 
}) 
.directive('graph', function() { 
    return { 
    restrict: 'E', 
    scope: { 
     values: '=' 
    }, 
    link: function(scope, element, attrs) { 
     scope.$watch('values', 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.population; 
      }); 

      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.population = +d.population; 
      }); 

      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.age); 
      }); 

      g.append("text") 
      .attr("transform", function(d) { 
       return "translate(" + arc.centroid(d) + ")"; 
      }) 
      .attr("dy", ".35em") 
      .style("text-anchor", "middle") 
      .text(function(d) { 
       return d.data.age; 
      }); 

     } 
     }) 
    } 
    } 
}); 

index.html

<!DOCTYPE html> 
<html> 

<head> 
    <meta charset="utf-8" /> 
    <title>AngularJS Plunker</title> 
    <script> 
    document.write('<base href="' + document.location + '" />'); 
    </script> 
    <link rel="stylesheet" href="style.css" /> 
    <script data-require="[email protected]" src="https://code.angularjs.org/1.0.8/angular.js" data-semver="1.0.8"></script> 
    <script data-require="[email protected]" src="https://code.angularjs.org/1.0.8/angular-resource.js" data-semver="1.0.8"></script> 
    <script data-require="[email protected]*" data-semver="3.2.2" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.2.2/d3.v3.min.js"></script> 
    <script src="app.js"></script> 
</head> 

<body ng-app="d3Test"> 
    <div ng-controller="IndicatorsCtrl"> 
    <graph values="values"></graph> 
    </div> 

</html> 
+1

danke für deine Antwort sollte es so funktionieren .. Ich arbeite jetzt mit NVD3 eckig. – LaymoO