带有矩形节点链接的D3版本4树视图未显示

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了带有矩形节点链接的D3版本4树视图未显示相关的知识,希望对你有一定的参考价值。

我正在研究d3.js版本4和角度5来构建树视图。我找到了Treeview的圆形节点示例(Example Here)。但是我将圆形节点更改为矩形。现在没有链接显示在树中。

Image of tree view with rectangle nodes and not showing links from parent to child.

Image of Tree view with expanded nodes.

Component.ts:

import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import * as d3 from 'd3';

@Component({
selector: 'app-rec-tree-view',
templateUrl: './rec-tree-view.component.html',
styleUrls: ['./rec-tree-view.component.css'],
encapsulation: ViewEncapsulation.None
})

export class RecTreeViewComponent implements OnInit {

margin = { top: 20, right: 120, bottom: 20, left: 120 };
width = 1200 - this.margin.right - this.margin.left;
height = 1200 - this.margin.top - this.margin.bottom;

tree = d3.tree().size([this.height, this.width]);
i = 0;
duration = 750;
root;
svg;
g;

constructor() { }

ngOnInit() {
 this.loadChart();
}

loadChart() {
this.svg = d3.select('#treeView').append('svg')
  .attr('width', this.width + this.margin.right + this.margin.left)
  .attr('height', this.height + this.margin.top + this.margin.bottom)
  .append('g')
  .attr('transform', 'translate(' + this.margin.left + ',' + this.margin.top 
   + ')');

this.root = d3.hierarchy(this.treeData, (d: any) => d.children);

 this.root.x0 = 0;
 this.root.y0 = this.height / 2;
 this.root.children.forEach(this.collapse);
 this.update(this.root);
}
collapse = (d) => {
 if (d.children) {
   d._children = d.children;
   d._children.forEach(this.collapse);
   d.children = null;
 }
}

update(source) {
const treeData = this.tree(this.root);
const nodes = treeData.descendants(),
  links = treeData.descendants().slice(1);

nodes.forEach((d) => { d.y = d.depth * 180; });

const node = this.svg.selectAll('g.node')
  .data(nodes, (d) => d.id || (d.id = ++this.i));

const nodeEnter = node.enter().append('g')
  .attr('class', 'node')
  .attr('transform', (d) => 'translate(' + source.y0 + ',' + source.x0 + 
   ')')
  .on('click', this.click);

nodeEnter.append('rect')
  .attr('width', 1e-6)
  .attr('height', 1e-6)
  .style('fill', function (d: any) {
    return d._children ? 'lightsteelblue' : '#fff';
  });

nodeEnter.append('text')
  .attr('dy', '.35em')
  .attr('x', -10)
  .text(function (d: any) { return d.data.name; });

const nodeUpdate = nodeEnter.merge(node);

nodeUpdate.transition()
  .duration(this.duration)
  .attr('transform', (d) => 'translate(' + d.y + ',' + d.x + ')');

const nodeHeight = 40,
  nodeWidth = 150;
nodeUpdate.select('rect')
  .attr('rx', 6)
  .attr('ry', 6)
  .attr('y', -(nodeHeight / 2))
  .attr('width', nodeWidth)
  .attr('height', nodeHeight)
  .style('fill', (d) => d._children ? 'lightsteelblue' : '#fff');


nodeUpdate.select('text')
  .style('fill-opacity', 1);

const nodeExit = node.exit().transition()
  .duration(this.duration)
  .attr('transform', (d) => 'translate(' + source.y + ',' + source.x + ')')
  .remove();

nodeExit.select('rect')
  .attr('width', 1e-6)
  .attr('height', 1e-6);

nodeExit.select('text')
  .style('fill-opacity', 1e-6);

const link = this.svg.selectAll('path.link')
  .data(links, (d) => d.id);

const linkEnter = link.enter().insert('path', 'g')
  .attr('class', 'link')
  .attr('d', (d) => {
    const o = { x: source.x0, y: source.y0 };
    return this.diagonal(o, o);
  });

link.transition()
  .duration(this.duration)
  .attr('stroke', 'black')
  .attr('d', this.diagonal);

link.exit().transition()
  .duration(this.duration)
  .attr('stroke', 'black')
  .attr('d', (d) => {
    const o = { x: source.x, y: source.y };
    return this.diagonal(o, o);
  })
  .remove();

nodes.forEach((d) => {
  d.x0 = d.x;
  d.y0 = d.y;
});

}


click = (d) => {
 if (d.children) {
  d._children = d.children;
  d.children = null;
} else {
  d.children = d._children;
  d._children = null;
}
this.update(d);
}

diagonal(s, d) {
const path = `M ${s.y} ${s.x}
            C ${(s.y + d.y) / 2} ${s.x},
              ${(s.y + d.y) / 2} ${d.x},
              ${d.y} ${d.x}`;

return path;
 }
}

CSS

.node {
   cursor: pointer;
 }

   .node circle {
     fill: #fff;
     stroke: steelblue;
     stroke-width: 1.5px;
   }

  .node text {
     font: 10px sans-serif;
   }

   .link {
     fill: none;
     stroke: rgb(236, 32, 5);
     stroke-width: 1.5px;
   }

   .node rect {
      fill: none;
      stroke: #636363;
      stroke-width: 1.5px;
   }
答案

您似乎错过了示例代码的“链接更新”部分:

  // UPDATE
  var linkUpdate = linkEnter.merge(link);

  // Transition back to the parent element position
  linkUpdate.transition()
      .duration(duration)
      .attr('d', function(d){ return diagonal(d, d.parent) });

您可能想要阅读D3V4中的changes to selections - 特别注意这个D3V3 append()行为已被弃用:

此外,selection.append不再将输入节点合并到更新选择中;使用selection.merge在数据连接后组合输入和更新。

以上是关于带有矩形节点链接的D3版本4树视图未显示的主要内容,如果未能解决你的问题,请参考以下文章

在 d3.js 中将节点和链接转换为分层树

如何实现 D3 层次视图

如何在 D3.js 中为网络图的矩形节点添加文本?

D3.js中Treemap(矩形树图)源码详解

D3.js中Treemap(矩形树图)源码详解

D3 具有非树数据的可折叠力有向图 - 链接对齐