我正在开发一个角度应用,需要以图表的形式显示一些数据。
我在nvd3.js
使用的图书馆。
图表是一个指令,创建图表的代码如下:
angular.module('charts', []).factory('d3', [
function() {
return d3;
}
]).factory('nv', [
function() {
return nv;
}
]).directive('hgCharts', [
'$timeout', 'd3', 'nv', function($timeout, d3, nv) {
var linkFunction;
linkFunction = function(scope, element, attr) {
var chart, chartCreated, containerHeight, containerWidth, createChart, date, svg, xScale;
containerWidth = element[0].offsetWidth;
containerHeight = element[0].offsetHeight;
date = new Date;
svg = element.find('svg');
chart = void 0;
xScale = d3.time.scale().domain([date, date]).nice(d3.time.day).range([0, containerWidth - 50]);
createChart = function() {
debugger;
chart = nv.models.multiChart();
chart.options({
showLegend: true,
duration: 0,
margin: {
'left': 20,
'right': 30,
'top': 50,
'bottom': 50
},
yDomain1: [0, 30],
showXAxis: false,
showMinMax: false,
useVoronoi: true
});
chart.xAxis.scale(xScale).orient('bottom').ticks(3).duration(0).tickFormat(d3.time.format('%H:%M'));
chart.yAxis1.orient('left').ticks(7).duration(0);
chart.tooltip.enabled(true);
nv.utils.windowResize(function() {
containerWidth = element[0].offsetWidth;
containerHeight = element[0].offsetHeight;
chart.xAxis.range([0, containerWidth - 50]);
chart.update();
return d3.selectAll(".nv-axisMaxMin-x")[0][0].remove();
});
return chart;
};
chartCreated = function() {
console.log("Scope.data is: ", scope.data);
d3.select(svg[0]).attr('width', '100%').attr('height', '100%').datum(scope.data).call(chart);
return d3.selectAll(".nv-axisMaxMin-x")[0][0].remove();
};
scope.$watch(function() {
return scope.data;
}, function() {
if (scope.data) {
console.log("Scope data changed...");
return nv.addGraph(createChart, chartCreated);
}
});
};
return {
restrict: 'E',
scope: {
data: '='
},
template: '<svg></svg>',
link: linkFunction
};
}
]);
在我的界面中,我有一个上一个和下一个按钮。
上面的每个按钮在控制器中都有一个功能,可以使用start
获得正确的end
和moment.js
时间段,一旦有正确的时间,就可以调用一个函数。
这是他们称之为函数的代码:
var loadChartData;
loadChartData = function(start, end) {
if (!start) {
start = 1467331200000;
}
if (!end) {
end = 1467417599000;
}
return hgChartData.loadData(start, end).then(function(res) {
return $scope.chartData = res;
});
};
该函数调用服务来加载我的数据,并将它们作为promise(res
)返回,然后使用新数据创建(或修改)$scope.chartData
。
调试这个过程很多,我注意到我遇到的问题是,即使$scope.chartData
发生了变化(我在控制台上打印了正确的结果),{{1}内的调试器也是如此永远不会调用函数,因此不会创建包含新数据的图表。
我是否对观察者做错了什么?
奇怪的是,它只在我第一次点击一个按钮时起作用(如果上一个或下一个没关系),但它会停止(如上所述,scope.chartData每次根据控制台改变我打印的消息。)next和prev按钮的代码如下:
createChart
我认为问题在于我的观察者,但我无法弄清楚我做错了什么。
感谢您的帮助
修改
经过多次调试之后,我发现范围实际上已经被观察了,但是一旦我更改为空阵列,它就不再被观看了。
我会更好地解释一下:
var requiredDay;
requiredDay = '';
$scope.prevDay = function() {
if (!requiredDay) {
requiredDay = moment(1467377134000);
}
requiredDay = requiredDay.clone().subtract(1, 'day');
console.log("Required data period is: ", requiredDay);
displayRequestedData(requiredDay);
return requiredDay;
};
$scope.nextDay = function() {
if (!requiredDay) {
requiredDay = moment(1467377134000);
}
requiredDay = requiredDay.clone().add(1, 'day');
console.log("Required data period is: ", requiredDay);
displayRequestedData(requiredDay);
return requiredDay;
};
(我在我的指令中观察的范围)等于一个对象数组,每个对象都有这种结构(直接从控制台获取):
scope.data
上一个对象中的每个数组都如下所示:
Object{
color:"red"
duration:0
key:"Temperature"
originalKey:"Temperature"
type:"line"
values:Array[10]
yAxis:1
}
我发现如果我的数组更改其值(数组值是该范围内唯一更改的内容),则更新范围并重新呈现图表,但只要我没有请求的数据时间段,我的对象内的数组数量变为0,然后观察者不再工作。
我希望这会有所帮助。我仍有问题试图理解为什么以及如何解决它。
再次感谢