使用 D3 在 DOM 中动态添加/删除 Angular 组件
Posted
技术标签:
【中文标题】使用 D3 在 DOM 中动态添加/删除 Angular 组件【英文标题】:Dynamically adding/removing Angular components to/from the DOM using D3 【发布时间】:2018-09-15 18:43:59 【问题描述】:我正在开发一个 Angular 组件 MyGraphComponent
,它应该使用 D3 显示一个图形,其中图形由一些 listOfEdges: Edge[]
和一些 listOfNodes: Node[]
给出,它们作为 MyGraphComponent
传递给 @Input
s。 listOfNodes
中的每个 individualNode
都应该作为 Angular 组件 <my-node [node]="individualNode">
显示在画布上,为给定的节点实例提供功能。 (想象一下,例如一个数据库模式编辑器,其中节点是可以编辑的表。)
现在,我想完全控制将节点添加到画布(即图形的 DOM)的方式和时间,因此,我不能只在图形组件的模板中使用 <my-node *ngFor="let node of listOfNodes">
。 (例如,我想添加动画,这些动画需要与正在使用 D3 的图形的边缘和其他部分的相应动画同步。)换句话说,我需要生成 MyNodeComponent
的所有实例动态,这样我就可以使用 D3 将它们添加到 DOM(然后在必要时删除它们)。
我找到了大量解释如何动态生成 Angular 组件的资源(参见例如1、2、3、4,尤其是5),但最后它们都使用 Angular 的 API 将这些组件添加到 ViewContainer
。但是,我想做的是使用 D3:
function generateAngularComponent(node: Node): MyNodeComponent
// Use Angular's component factory to dynamically create
// an instance of MyNodeComponent here and return it. See
// the links for code examples.
let nodes: Node[] = [node1, node2, node3, ...];
d3.select(".my-canvas").selectAll(".my-node").data(nodes).enter()
.append(node =>
let component = generateAngularComponent(node);
// Somehow return the DOM of the component here, so that
// D3 adds it to the canvas
);
我该如何做到这一点——不破坏我的MyNodeComponent
、它的变更检测、依赖注入等等?这可能吗?
【问题讨论】:
【参考方案1】:是的,有可能。我为我的应用程序创建了一个旭日形图。我创建了一个带有其类型的图表组件并将其封装在一个模块中。这是结构 -
|charts.module.ts
├──sun-burst/
| ├──sun-burst-chart.component.ts
| ├──sun-burst-chart.component.html
| ├──sun-burst-chart.component.scss
├──some-other chart/
| ├──...ts
这是我的示例图表组件。我已经删除了不必要的细节。
import Component, Input, ElementRef, Renderer, OnChanges from '@angular/core';
import * as d3 from 'd3';
export class SunburstChartComponent implements OnChanges
// inputs
// objects related to chart like svg
private htmlElement: HTMLElement;
public constructor(public renderer: Renderer, public el: ElementRef)
this.htmlElement = el.nativeElement;
public ngOnChanges()
// remove previously added element when data changes
d3.select(this.htmlElement).selectAll('svg').remove();
this.displayChart();
public displayChart()
// this requires some additional work before chart can be prepared, refer d3 documentation for your component
this.svg = d3.select(this.htmlElement).append('svg')
.attr('width', this.width)
.attr('height', this.height)
.append('g')
.attr('transform', 'translate(' + this.width / 2 + ',' + (this.height / 2) + ')');
// handle additional functions required for your chart like click, tween etc., refer samples for your component from d3 website.
private click(d, arc)
您需要保留在 d3 组件中添加的某些元素的引用以进行操作。它根据您创建的组件而有所不同。
我希望这会有所帮助。 如果您遇到任何问题,请在 stackblitz 上创建一个示例并分享。
【讨论】:
以上是关于使用 D3 在 DOM 中动态添加/删除 Angular 组件的主要内容,如果未能解决你的问题,请参考以下文章
D3.js入门 select选择器 元素的插入和删除 dataum和data 动态属性
D3.js入门 select选择器 元素的插入和删除 dataum和data 动态属性