在Angular
中使用D3
制作图表,我们可以根据图表的种类创建不同的指令和对应的服务。比如创建一个柱状图时,我们在模块下创建一个barChart
指令:
myComponents.directive('barChart', function($compile) {
'use strict';
return {
restrict: 'AE',
scope: {
chartTitle: "@", //图表标题
series: "=", //图标的数据
height: "=?height" //图表的高度
},
controller: function(initBarChart, $scope, $element, $attrs) {
$scope.height = $scope.height || 200; //如果高度未定义,则使用默认值200
var _chart = initBarChart($scope); //使用服务
var _chartBody = $element.find(".chart-body"); //获取图表的容器
_chartBody.height($scope.height); //设置容器的高度
_chart.generate($element.find(".chart-body"), $scope.series, { //使用服务提供的方法生成图表
height: $scope.height,
});
//Do something here...
},
template: '<div class="chart">' + '<div class="chart-header">' + '<h3>{{chartTitle}}</h3>' +
'</div>' + '<div class="chart-body">' + '</div>' + '</div>',
replace: true
};
});
对应的initBarChart
服务:
myComponents.service('initBarChart', function() {
'use strict';
var charts = function($scope) {
return {
generate: function(ele, series, config) {
ele = $(ele);
series = series || [];
config = config || {};
d3.select(id).selectAll('.svg_barchart').remove();
//添加svg元素
var svg = d3.select(id).append("svg")
.attr('class', 'svg_barchart')
//Do something here...
},
};
return charts;
});
我们只需要把D3制作柱状图的关键代码放到generate
方法中就可以了。
在页面中使用这个指令:
<div bar-chart height="300" chart-title="操作次数" data-series="operationSeries"></div>
然后在作用范围包含这个节点的$scope
中定义变量operationSeries
,用于传递图表中要显示的数据或者配置参数。
监听图表数据的变化
使用Ajax获取数据并进行处理后,发现图表显示不出来。在Chrome的ng-inspect
插件中看到$scope.series
是有数据的,但是图表中获取不到这个series
的值。后来想到可能是图表绘制的时候,series的数据还没有处理好。
于是决定在指令对应的控制器中,使用$watch
监听series
变量的变化:
//检测数据变化,更新图表
$scope.$watch('series', function(newData, oldData){
if(!angular.equals(newData,oldData)){
_chart.generate($element.find(".chart-body"), newData, {
height: $scope.height,
});
}
}, true);