我相信我有一个问题,可能很容易通过我错过的东西来解决,但我似乎看不出实际的问题是什么。我有一个应用程序,它每秒钟返回5000点(1000x,y点的5个数组元素),我想使用NVD3在客户端更新。这是一个AngularJS应用程序,所以我使用krispos angular-nvd3指令。然而,它使整个应用程序陷入困境,而且根据Chrome开发工具捕捉到的时间线,该应用程序似乎在等待d3_timer_step返回5-6秒。
我认为这个问题是由于我们如何更新数据,但整个问题似乎与实际的d3部分有关。客户端的代码是
<nvd3 options="optionsRingdown" data="ringdownAvg" config="{refreshDataOnly:true}"></nvd3>在控制器中,选项定义如下
$scope.options = {
chart: {
type: 'lineChart',
height: 300,
margin: {
top: 20,
right: 40,
bottom: 60,
left: 75
},
x: function(d) {
return d.x;
},
y: function(d) {
return d.y;
},
useInteractiveGuideline: false,
yAxis: {
tickFormat: function(d) {
return d3.format('0.01f')(d);
},
axisLabel: 'Testing'
},
xAxis: {
tickFormat: function(d) {
return d3.time.format('%X')(new Date(d));
},
rotateLabels: -45
},
transitionDuration: 0,
showXAxis: true,
showYAxis: true
}
};数据在下面的模板中定义
var ringdownT = [{
values: [],
key: 'Cell 0'
}, {
values: [],
key: 'Cell 1'
}, {
values: [],
key: 'Cell 2'
}, {
values: [],
key: 'Cell 3'
}, {
values: [],
key: 'Cell 4'
}];通过从服务广播的函数调用,使用以下方法更新数据
function updateCRD(d){
var dataOut = {
"tauData": [],
"rdFit": ringdownT,
"rdAvg":ringdownT
}
for (k = 0; k < d.cell.length; k++) {
dataOut.rdAvg[k].values = d.cell[k].avg_rd;
dataOut.rdFit[k].values = d.cell[k].fit_rd;
}
return dataOut;
}该函数在广播中使用以下方式调用(每隔1秒广播一次)
$scope.$on('dataAvailable', function() {
$scope.data = Data.crd;
var data = updateCRD(Data.crd);
$scope.tauData = data.tauData;
$scope.ringdownAvg = data.rdAvg;
$scope.ringdownFit = data.rdFit;
});有没有人在这里看到明显不对劲的东西,或者我应该采取不同的做法?我错过了什么选择吗?任何帮助都会很好。
干杯,马特
发布于 2015-09-25 22:45:05
尝试在配置中添加deepWatchData: false标志(这意味着该指令不会监视更新的数据)并通过api更新图表
<nvd3 options="optionsRingdown" data="ringdownAvg" api="apiRingdown" config="{refreshDataOnly:true, deepWatchData: false}"></nvd3>该指令监视选项和复杂数据对象,以便使用$watch(watchExpression, listener, [objectEquality])方法进行任何更新。在我们的示例中,deepWatchData是objectEquality标志,同时监视图表数据以进行更新。
根据角文档,根据angular.equals函数确定watchExpression的不等式。为了保存对象的值以便以后进行比较,使用了angular.copy函数。因此,这意味着观察复杂的对象会对内存和性能产生不利影响。
仅在版本(1.0.2,1.0.3)中,默认情况下此标志为false。
然后,要更新图表,我们可以在控制器中使用apiRingdown.update方法:
$scope.$on('dataAvailable', function() {
$scope.data = Data.crd;
var data = updateCRD(Data.crd);
$scope.tauData = data.tauData;
$scope.ringdownAvg = data.rdAvg;
$scope.ringdownFit = data.rdFit;
//this line updates the chart
$scope.apiRingdown.update();
});已更新
在最新版本的1.0.4+中添加了一些更新。现在,标记deepWatchData意味着使用或不使用数据监视(它不像以前那样是objectEquality )。默认情况下,deepWatchData是true。但是现在我们可以使用一个新的标志$watch来管理deepWatchDataDepth: 2深度,从而调节性能。使用此标志,我们可以为数据指定一个更改检测策略(范围$watch深度):
0 - By Reference (the least powerful, but the most efficient)
1 - By Collection Items
2 - By Value (the most powerful, but also the most expensive; default value)此外,默认情况下,标志refreshDataOnly是true。
因此,更新后的标记元素可能如下所示:
<nvd3 options="optionsRingdown" data="ringdownAvg" api="apiRingdown" config="{deepWatchDataDepth: 0}"></nvd3>发布于 2015-09-25 15:34:42
你在用SVG吗?nvd3.lineChart是SVG,所以可能是的。如果是这样的话,@mbostock为您提供了答案:http://bl.ocks.org/mbostock/1276463。使用canvas而不是SVG来获得更快的速度。
大多数关于https://www.safaribooksonline.com/blog/2014/02/20/speeding-d3-js-checklist/的建议都是非常可靠的。
你每秒钟要重画5000点吗?如果是这样的话,这是webGL的工作,而不是nvd3。canvas可能足够快,如果画布不够快,那么我将坚持以前的答案。
花在d3_timer_step上的时间是多少?这是没有道理的,该功能将是缓慢的,它可能只是被称为很多次。实际上,d3_timer_frame是由d3_timer_step调用的,这可能是实际的呈现代码,肯定会占用您所有的时间。试着做canvas。
可能的nvd3性能改进:
useInteractiveGuideline,那么一定要禁用它。https://stackoverflow.com/questions/32785163
复制相似问题