我有一个关于使用 AngularJS 和 D3 的应用程序的有趣问题。本质上,我有一个 ng-repeat,它根据数组的内容重复。在这个数组中是包含一个 REST url 的对象,它们将定期访问并从中提取数据。一旦他们获得这些数据,就会使用 D3 绘制图表(数组中的每个对象对应一个图表)。
我遇到的问题是通过用户输入将对象动态添加到此数组,并使绘图正常工作。看起来 d3 代码抢先一步,开始尝试选择尚未渲染的 SVG 元素,因为 Angular 仍在通过 ng-repeat 向 DOM 添加内容。
我已经尝试使用 $timeout,并且还创建了一个类似于此的自定义指令:ng-repeat finish event .
它运行良好,但似乎只在第一次运行 ng-repeat 时触发事件,而不是在我将另一个对象添加到数组时触发事件。对处理这种情况的最佳方法有何评论?如果我可以在每次添加/删除新对象时基于 $last 触发事件,然后遍历数组并调用绘图函数,这似乎可行。
干杯!
编辑:D3 代码目前与此类似 http://bl.ocks.org/mbostock/1346410这只是一个简单的圆环图更新,需要注意的是重绘是由 REST 调用触发的。然而,将来可能会有更复杂的图表,这就是我希望使用 D3 的原因。
编辑 2:我已将我所有的 D3 代码移到一个自定义指令中,经过大量修改后,它似乎几乎可以正常工作。通过不隔离范围,自定义元素与 ng-repeat 具有相同的范围,并且可以访问对象及其属性,以及相关的 DOM 元素(目前我正在创建一个 DIV,每个对象都有一个唯一的 ID ).
现在使用 d3.select 时出现问题...当我尝试选择要放置绘图的 DIV 时,它不允许我按 ID 选择,因为它返回 null..这很奇怪关于这一点,如果我 selectAll("div"),它可以找到我正在寻找的 div,但不会让我只选择那个。
这是一个 JsFiddle 显示我的意思...检查控制台并看到第一个测试返回 div“obj1”,但第二个选择返回 null。
如果我能让它工作,然后在那个 div 中附加我的 SVG Canvas 和绘图,我认为它会工作!
相关选择:
var test = d3.selectAll("div");
console.log(test);
var chart = d3.select("#obj" +obj.id);
console.log(chart);
应该创建 div 的 HTML:
<div ng-repeat="object in myData">
<div id="obj{{object.id}}">
Hi
<bars-chart></bars-chart>
</div>
</div>
http://jsfiddle.net/SleepyProgrammer/eN6p7/3/
最佳答案
根本不需要使用ID进行选择。您可以简单地选择传递给 Angular 指令的 link
函数的 element[0]
:
var chart = d3.select(element[0]).append('svg')
例如:
angular.module('myApp', []).
directive('barsChart', function () {
return {
restrict: 'E',
link: function (scope, element, attrs) {
var chart = d3.select(element[0]).append('svg').attr({height: 20, width: 20});
chart.append('rect').attr({height: 10, width: 10});
}
};
});
function Ctrl($scope, $timeout) {
$scope.myData = [ {"id":"1"}, {"id":"2"}];
// just to show that it reacts to changes in the data and will render more SVGs
$timeout(function() {
$scope.myData.push({"id":"3"});
}, 3000);
}
在这里查看 JSFiddle:
http://jsfiddle.net/4vdvq/2/
https://stackoverflow.com/questions/23199859/