我正在使用实时数据在网页上使用SVG绘制一些线条。为了管理我使用Angular.js的数据并管理可视化,我使用D3.js.
我设置一个角度控制器来保存数据(线)。数据由一些点数组成(带有x / y坐标的字典)。有些行在初始化时已知,其他行根据实时数据更新。
我设置了一个包含SVG元素的角度指令(' topView')。对于初始化时的每一行,我使用以下命令将其添加为路径:
var routeLeftLine = container.select("#routes").append("path");
var routeLeftLineData = scope.val.route.left; // -> 1000+ points in there
routeLeftLine
.attr("d", lineFunction(routeLeftLineData))
.attr("stroke", "black")
.attr("stroke-width", 1)
.attr("fill", "none");
对于我想要不断更新的每一行(1),我设置了一个角度指令,例如:
<surface-cable val="data.cable"></surface-cable>
其中data是我控制器上的数据对象,data.cable是点数组。 该指令如下所示:
OCMSWeb.directive('surfaceCable', function ( /* dependencies */ ) {
return {
restrict: 'AE',
scope: {
val: '='
},
templateNamespace: 'svg',
replace: true,
template: '<g/>',
link: function (scope, element, attrs) {
var cableLine = d3.select(element[0]).append("path");
scope.$watch('val', function () {
var cableLineData = simplify(scope.val, 1, false); // size grows in time
cableLine
.attr("d", lineFunction(cableLineData))
.attr("stroke", "rgb(240,144,32)")
.attr("stroke-width", 1)
.attr("fill", "none");
}, true);
}
};
});
当我使用计时器更新数据时,结构工作正常,更改反映在SVG中。
当我增加一行中的点数(> 1000,我将来还需要更多)时出现问题(两者都是不变的,更新的行都有这个效果)性能下降。即使要重绘的元素还不包含许多元素,行的更新也会变得非常慢。
我无法找到原因。 SVG / d3 / angular是否再次渲染svg中的所有元素?
我绑定数据的方式效率低下吗?我应该一起跳过d3吗?
我试图分析javascript的性能,大约80-90%的CPU时间似乎是针对angular $ apply的调用(我认为,扫描DOM进行更改?)。如果元素(行是<path>
元素)有很多数据点,为什么$ apply需要这么长时间呢?
答案 0 :(得分:1)
使用此体系结构,每次更改范围内的任何内容时,1000行表示1000个指令,1000个监视和1000个值比较,无论这些值是否实际更改。我怀疑这里的根本问题是你的d3代码,虽然不必要地重新设置笔画,笔画宽度和填充的属性肯定没有帮助。
一般来说,更好的方法是使用单个指令获取行数并处理SVG中所有电缆路径的布局。如果您正在查看数以千计的路径,那么您可能希望在画布上而不是SVG上进行渲染。
答案 1 :(得分:0)
虽然@ ethan-jewett没有完全回答我的问题,但是你做到了 然而,我指出了正确的方向。
因为我将控制器的'data'字典(包含静态和动态数据)链接到指令,我假设angular会检查其中的所有值以进行更改。通过将静态数据移出此“数据”字典,它不会被检查并使此设置更快。
当我增加动态数据的大小时,分析仍会产生角度变慢,我认为这是出于同样的原因(角度需要检查所有数据的变化)。我不确定我将如何解决这个问题:我将研究D3.js是否有更有效的机制来检测数据中的变化,或者我会将我的长阵列分成静态和动态部分(因为它们代表路径/电缆,只有电缆的末端才能真正改变。在某些时候,电缆的很大一部分可以被认为是静态的。)。