在学习这两种框架的背景下,我正在尝试不同的集成D3和Angular的方法,并希望得到一些输入:
我的客户端应用程序从我的服务器接收一个JSON节点数组和一个边缘数组。客户端的核心组件是一个以D3力为导向的布局实现的图形可视化:对于节点数组中的每个节点,在该可视化中添加一个(SVG)圆元素,并为边缘数组中的每个边缘添加这些圆圈之间的线条。
当然,D3的selection.data( )
使添加这些元素并将每个元素绑定到它所表示的数据变得非常简单,但是图形可视化只是一个大得多的应用程序的一部分:我需要创建不同类型的元素,它们代表应用程序不同部分中的相同节点和边缘(D3与此无关),我希望将所有这些元素绑定到一个数据集中。
我的主要目标是最小化代码复杂性,尽管我爱上了d3的数据绑定功能的简单性和优雅性,但我得出了一个初步的结论:在应用程序的一个部分使用它,而在其他部分使用它来做同样的事情,就会产生不必要的复杂性,而最简单的方法将是使用角来处理数据绑定/元素创建。
换句话说,与其使用selection.data( ).enter( ).append( )
来创建SVG元素,我还认为我应该使用ng-repeat="node in nodes"
来创建这些元素,也许可以将它们作为一个自定义指令来创建,以允许自定义功能。这样做之后,我就需要将这些元素“放入”D3,即由其强制导向的布局来管理。
是我在这里的推理吗?尤其是,我担心我忽略了这会造成物体恒定性的复杂情况,这是一个重要的要求,因为节点将不断地进入、退出和移动屏幕,我需要这些转换是平滑的。您建议我如何将角创建的元素集成到D3中(更准确地说,将它们放到force.nodes{ }
和force.links( )
数组中),以避免任何这样的复杂情况?
最后,我还在考虑一种策略,我希望这两种策略都能给我最好的结果:我可以使用D3来创建SVG元素并将它们绑定到它们各自的数据,但是与其在可视化指令的link
函数中执行该代码(就像我一直在做的那样,而且正如我发现的所有角/d3教程所做的那样),我可以在compile
函数中运行它,并执行如下操作:
d3.select('SVG')
.selectAll('.node')
.data('nodeDataArray')
.enter( )
.append('circle')
.attr("class", "node-icon"); //...other attributes/styles etc
其中,node-icon
是带有包含C
的restrict
属性的指令的规范化名称。如果这在compile方法中运行,angular应该按照正常的方式编译所有这些指令,添加任何附加的功能/接口到其他指令(等等),就像它对任何其他类型的元素所做的那样。对吗?
这是我最直观地被吸引的选择--我可能会忽略其中的任何缺陷,这可能会使前一种策略更可取吗?
发布于 2014-06-09 05:13:33
我已经思考了几乎相同的问题一段时间,并得出以下结论。
将角创建元素与d3集成的最简单方法是使用.attr
添加指令,然后在d3生成的元素上添加编译服务.call
。如下所示:
mySvg.selectAll("circle")
.data(scope.nodes)
.enter()
.append("circle")
.attr("tooltip-append-to-body", true)
.attr("tooltip", function(d){
return d.name;
})
.call(function(){
$compile(this[0].parentNode)(scope);
});
我认为用角度ngRepeat
而不是d3生成元素的想法与框架背道而驰。D3不希望得到一堆元素。它希望得到数据--几乎总是一个数组。然后,它拥有一堆优秀的函数,可以将数据转换为各种SVG或HTML元素。让它这么做吧。
从这句话看来..。
D3使添加元素并将每个元素绑定到它所表示的数据变得非常简单,但图形可视化只是一个大得多的应用程序的一部分:我需要创建不同类型的元素,它们代表应用程序不同部分中的相同节点和边缘( D3与此无关),我希望将所有这些元素绑定到一个数据集中。
..。您的意思是用d3生成元素会在某种程度上阻止您将相同的数据绑定到应用程序的不同部分。我不明白为什么。让d3从作用域数组生成元素(就像在链接柱塞中所做的那样)。然后以通常的角度方式在任何地方使用相同的数据集。应用程序的其他部分可以更新数据集,$watch
回调可以重新呈现d3图形。
https://stackoverflow.com/questions/23231587
复制