如何使用指令显示D3 Chart?

时间:2016-04-18 23:04:38

标签: angularjs d3.js angularjs-directive

我试图从JSON对象显示饼图。

当我尝试使用此对象时,它可以工作:

[{
  "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
  }]
}]

但只有这个:

[{
  "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
}]

这是我的代码:



 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 () {
	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; });

				}
			})
		}
	}
});

<!DOCTYPE html>
<html>

<head>
  <script data-require="angular.js@*" data-semver="1.0.7" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js"></script>
  <script data-require="angular-resource@1.0.7" data-semver="1.0.7" src="http://code.angularjs.org/1.0.7/angular-resource.min.js"></script>
  <script data-require="d3@*" 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>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:0)

我认为你可能会错误地调用你的<graph />指令(或者将你的指令修改为双向绑定compositeObject,然后调用compositeObject.values);当前编写指令的方式,您应该传递值,而不是对象。

此外,如果您希望<graph />在任何数据更改时自动更新,您需要执行某种深度$watch(传递值true作为第三个论点)。我一会儿将这些d3图表包装在Angular的仪表板中...... although consider using a library for your charts

以下是您的代码中的一个示例(我使用的是1.0.8而不是1.0.7,因为您的链接是https):

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="angular.js@1.0.x" src="https://code.angularjs.org/1.0.8/angular.js" data-semver="1.0.8"></script>
  <script data-require="angular.js@1.0.x" src="https://code.angularjs.org/1.0.8/angular-resource.js" data-semver="1.0.8"></script>
  <script data-require="d3@*" 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>