简体   繁体   English

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

[英]D3 version 4 tree view with rectangle nodes links not showing up

I'm working on d3.js version 4 and angular 5 to build treeview. 我正在使用d3.js版本4和angular 5来构建treeview。 I found Treeview with circular nodes example( Example Here ). 我发现带有圆形节点的Treeview示例( 此处为示例 )。 But i changed circular nodes to rectangle.Now links are not showing up in tree. 但是我将圆形节点更改为矩形。现在链接未显示在树中。

Image of tree view with rectangle nodes and not showing links from parent to child. 具有矩形节点且未显示父级到子级的链接的树形视图的图像。

Image of Tree view with expanded nodes. 树视图的图像与扩展的节点。

Component.ts : 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 的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;
   }

Looks like you missed the "Link Update" section of the example code: 您似乎错过了示例代码的“链接更新”部分:

  // 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) });

You may want to read up on the changes to selections that are in D3V4 -- Note especially that this D3V3 append() behavior has been deprecated: 您可能需要阅读D3V4中对选择所做的更改 -特别注意,此D3V3 append()行为已被弃用:

In addition, selection.append no longer merges entering nodes into the update selection; 此外,selection.append不再将输入的节点合并到更新选择中; use selection.merge to combine enter and update after a data join. 在数据联接之后,使用selection.merge组合回车和更新。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM