如何显示具有中心根的两棵树?

时间:2019-03-29 21:39:46

标签: javascript angular d3.js

我正在尝试创建两棵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。 这导致只有我的左树可见。

left tree

在我的TreeModel代码中,我可以通过在leftTreeUpdate之前调用rightTreeUpdate来显示右边的树,而不显示左边的树 在我的click()函数中。

enter image description here

我怀疑自己在setNodes()setLinks()方法中做错了,因为我真的不了解nodeEnternodeUpdate和{{1 }}。

这里是我的nodeExit的编辑版本(为简洁起见)。

TreeModel

1 个答案:

答案 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)
      });

这就是我现在的两棵树。

enter image description here

我仍然需要正确地绘制左侧的链接,但这是另一个问题。谢谢安德鲁!