简体   繁体   中英

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. I found Treeview with circular nodes example( Example Here ). 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 :

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

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:

In addition, selection.append no longer merges entering nodes into the update selection; use selection.merge to combine enter and update after a data join.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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