将Angular创建的元素与D3集成的最简单方法

dre*_*ore 10 javascript data-binding d3.js angularjs

在学习这两个框架的背景下,我正在玩不同的集成D3和Angular的方法,并希望得到一些输入:

我的客户端应用程序从我的服务器接收JSON节点数组和一组边.客户端的核心组件是一个图形可视化,实现为D3力导向布局:对于节点阵列中的每个节点,将一个(SVG)圆形元素添加到此可视化中,并为每个边缘添加这些圆圈之间的线条.边缘数组.

当然,D3 selection.data( )使得添加这些元素并将每个元素绑定到它所代表的数据变得微不足道,但是图形可视化只是更大应用程序的一部分:我需要创建不同类型的元素来表示不同部分中的这些相同节点和边缘应用程序(D3与之无关),我想将所有这些元素绑定到单个数据集.

我的主要目标是最大限度地降低代码复杂性,并且 - 尽管我已经爱上了D3的数据绑定功能的简单性和优雅性 - 我得出的初步结论是,在使用Angular时,在应用程序的一部分中使用它在其他部分做同样的事情会产生不必要的复杂性,最简单的方法是使用Angular来处理数据绑定/元素创建

换句话说,我不是selection.data( ).enter( ).append( )用来创建SVG元素,而是想我应该使用a ng-repeat="node in nodes",也许创建每个作为自定义指令以允许自定义功能.完成后,我需要将这些元素"放入"D3,即由其强制导向布局管理.

我的理由在这听起来吗?特别是,我担心我会忽略这将在对象恒定性方面产生的复杂性,这是一个重要的要求,因为节点将不断地进入,退出和移动屏幕,我需要这些过渡是平滑的.您如何建议我将我的角度创建元素集成到D3中(更确切地说,将它们放入我的force.nodes{ }force.links( )数组中)以避免任何此类复杂情况?

最后,我还在考虑一种策略,我希望可以给我两全其美:我可以使用D3创建我的SVG元素并将它们绑定到各自的数据,但不是在link函数中执行可视化指令(正如我一直在做的,以及我发现的所有Angular/D3教程),我可以在compile函数中运行它,并执行以下操作:

d3.select('SVG')
  .selectAll('.node')
  .data('nodeDataArray')
  .enter( )
  .append('circle')
  .attr("class", "node-icon"); //...other attributes/styles etc  
Run Code Online (Sandbox Code Playgroud)

where node-icon是具有包含的restrict属性的指令的规范化名称C.如果这在compile方法中运行,则angular应该正常编译所有这些指令,添加任何其他功能/接口与其他指令(等),就像它对任何其他类型的元素一样.对?

这是我最直观的选择 - 我可能会忽略它的任何陷阱,这可能会使前一种策略更可取吗?

dav*_*004 4

一段时间以来,我一直在思考几乎同样的问题,并得出以下结论。

将 Angular 创建的元素与 d3 集成的最简单方法是添加指令.attr,然后.call在 d3 生成的元素上添加编译服务。像这样:

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);
                });
Run Code Online (Sandbox Code Playgroud)

这是一个笨蛋

我认为使用 Angular 而不是 d3 生成元素的想法与ngRepeat框架背道而驰。D3 并不期望收到一堆元素。它想要传递数据——几乎总是一个数组。然后,它具有一系列出色的功能,可以将该数据转换为各种 SVG 或 HTML 元素。让它这样做。

从这句话看来...

D3 使得添加元素并将每个元素绑定到它所代表的数据变得很简单,但图形可视化只是更大应用程序的一部分:我需要在应用程序的不同部分创建代表这些相同节点和边的不同类型的元素( D3 与此无关),并且我希望将所有这些元素绑定到单个数据集。

...您暗示使用 d3 生成元素会以某种方式阻止您将相同的数据绑定到应用程序的不同部分。我不明白为什么。只需让 d3 从作用域数组生成元素(如链接的 Plunker 中所做的那样)。然后以通常的 Angular 方式在任何需要的地方使用相同的数据集。应用程序的其他部分可以更新数据集,并且$watch回调可以重新渲染 d3 图形。