我正在尝试创建两棵D3树,它们似乎是共享中心根。用户单击我的节点时,树应向左右扩展。
我在这里遇到了一个关于stackoverflow的示例。
以下是该SO的链接:Tree with children towards multiple side in d3.js (similar to family tree)
我什至在这里将这段代码的bl.ocks.org版本放在一起:https://bl.ocks.org/redcricket/de324f83aa6c84db2588c1a1f53cc5e3
以上示例是D3 v3。我将上面的示例改编为D3 v4,并将其集成到一个角度组件中, 但是我遇到了一个问题,一次只能显示一棵树。
我的代码的入口点是这个角度组件及其服务组件:
组件:
import { Component, OnInit, OnChanges, ViewChild, ElementRef, Input, Output, EventEmitter} from '@angular/core';
import { AngularD3TreeLibService } from './custom-d3-tree.service';
@Component({
selector: 'custom-angular-d3-tree-lib',
template: `<div class="d3-chart" #chart></div> `,
styleUrls: ['./custom-d3-tree.component.css']
})
export class AngularD3TreeLibComponent implements OnInit, OnChanges {
@ViewChild('chart') private chartContainer: ElementRef;
@Input() treeData: any = [];
@Output() onNodeChanged: EventEmitter<any>= new EventEmitter();
@Output() onNodeSelected: EventEmitter<any>= new EventEmitter();
constructor( private treeService: AngularD3TreeLibService ) {
treeService.setNodeChangedListener((node)=>{ this.onNodeChanged.emit(node); })
treeService.setNodeSelectedListener((node)=>{ this.onNodeSelected.emit(node); })
}
ngOnInit() {}
ngOnChanges(changes: any) { this.seedTree(); }
seedTree(){
if(!!this.treeData){
this.treeService.createChart(this.chartContainer, this.treeData);
this.treeService.update();
}
}
}
服务:
import { Injectable } from '@angular/core';
import { TreeModel } from './tree.dendo.model';
@Injectable({
providedIn: 'root'
})
export class AngularD3TreeLibService {
treeModel: TreeModel= new TreeModel();
constructor() { }
createChart(chartContainer: any, treeData: any): void {
let element = chartContainer.nativeElement;
element.innerHTML= "";
this.treeModel.addSvgToContainer(chartContainer);
this.treeModel.createLayout();
this.treeModel.createTreeData(treeData);
}
update(){
this.treeModel.rightTreeUpdate(this.treeModel.rroot);
this.treeModel.leftTreeUpdate(this.treeModel.lroot);
}
}
在AngularD3TreeLibService.update()
方法中请注意,在调用rightTreeUpdate
之前,我先调用leftTreeUpdate
。
这导致只有我的左树可见。
在我的TreeModel代码中,我可以通过在leftTreeUpdate
之前调用rightTreeUpdate
来显示右边的树,而不显示左边的树
在我的click()
函数中。
我怀疑自己在setNodes()
和setLinks()
方法中做错了,因为我真的不了解nodeEnter
,nodeUpdate
和{{1 }}。
这里是我的nodeExit
的编辑版本(为简洁起见)。
TreeModel
答案 0 :(得分:2)
在遵循安德鲁·里德(Andrew Ried)的建议之后,我仅需更改四行代码就可以绘制两棵树。
在我的setNodes()
方法中,我现在有了这个:
// var node = this.svg.selectAll('g.node')
var node = this.svg.selectAll('g.node'+side)
.data(nodes, function(d) { return d.id || (d.id = ++this.i); });
var nodeEnter = node.enter().append('g')
// .attr('class', 'node')
.attr('class', 'node'+side)
.attr("transform", function(d) {
return " translate(" + source.y0 + "," + source.x0 + ")";
});
和我的setLinks
方法中的类似更改:
var link = this.svg.selectAll('path.link'+side)
.data(links, function(d) { return d.id; });
// Enter any new links at the parent's previous position.
var linkEnter = link.enter().insert('path', "g")
.attr("class", "link"+side)
.attr('fill', 'none')
.attr('stroke', 'black')
.attr('d', (d)=>{
var o = {x: source.x0, y: source.y0}
return this.rdiagonalCurvedPath(o, o)
});
这就是我现在的两棵树。
我仍然需要正确地绘制左侧的链接,但这是另一个问题。谢谢安德鲁!