简体   繁体   中英

collapsible trees in typescript and d3 version v3

I am trying to create collapsible trees with d3 ( https://bl.ocks.org/mbostock/4339083 ) in Angular4 project using typescript. My trees is not getting generated for all nodes only last node is displaying. Can someone help how to create d3 collapsible trees in typescript

There is some iteration or loop issues i guess all nodes are not iterated.

const data =
  {
    "name": "Top Level",
    "children": [
      {
        "name": "Level 2: A",
        "children": [
          { "name": "Son of A" },
          { "name": "Daughter of A" }
        ]
      },
      { "name": "Level 2: B" }
    ]
  };



export class ClusterChartComponent implements OnInit{

  //@ViewChild('container') private chartContainer: ElementRef;
  private margin: any = {top: 20, right: 120, bottom: 20, left: 120};
  private width: number;
  private height: number;
  private i = 0;
  private duration = 750;
  private root: any;
  private tree;
  private svg;
  private diagonal;

  constructor() {
  }


  ngOnInit() {
    this.width = 960 - this.margin.right - this.margin.left;
    this.height = 800 - this.margin.top - this.margin.bottom;

    this.tree = d3.layout.tree()
      .size([this.height, this.width]);

    this.diagonal = d3.svg.diagonal()
      .projection((d) => { return [d.y, d.x]; });

    this.svg = d3.select('.container').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 + ")");

    console.log("flare inside",data);
    this.root = data;
    this.root.x0 = this.height / 2;
    this.root.y0 = 0;


    this.root.children.forEach(this.collapse);
    this.update(this.root);


    //d3.select(self.frameElement).style("height", "800px");

  }

  collapse = (d) => {
    if (d.children) {
      d._children = d.children;
      d._children.forEach(this.collapse);
      d.children = null;
    }
  };

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

  update (source): any {

    let nodes = this.tree.nodes(this.root).reverse()
    let links = this.tree.links(nodes);
    nodes.forEach(function(d){ d.y = d.depth * 180});

    // Update the nodes…
    let node = this.svg.selectAll('g.node')
      .data(nodes, function (d: any) {
        return d.id || (d.id = ++this.i);
      });

    // Enter any new nodes at the parent's previous position.
    var nodeEnter = node.enter().append('g')
      .attr('class', 'node')
      .attr('transform', function () {
        return 'translate(' + source.y0 + ',' + source.x0 + ')';
      })
      .on('click', this.click);



    // Add Circle for the nodes
    nodeEnter.append('circle')
      .attr('r', 1e-6)
      .style('fill', function (d: any) {
        return d._children ? 'lightsteelblue' : '#fff';
      });
    // Add labels to the nodes
    nodeEnter.append('text')
      .attr('x', function (d: any) {
        return d.children || d._children ? -10 : 10;
      })
      .attr('dy', '.35em')
      .attr('text-anchor', function (d: any) {
        return d.children || d._children ? 'end' : 'start';
      })
      .text(function (d: any) {
        return d.name;

      })
      .style('fill-opacity', 1e-6);

    //i have to see whats this

    d3.select('svg').transition()
      .duration(this.duration)
      .attr("height", this.height);


    nodeEnter.append('svg:title').text(function (d: any) {
      return d.name;
    });




    // Transition to the proper position for the node
    var nodeUpdate =  node.transition()
      .duration(this.duration)
      .attr('transform', function(d) {
        return 'translate(' + d.y + "," + d.x + ')';
      });

    // Update the node attributes and style
    nodeUpdate.select('circle')
      .attr('r', 10)
      .style('fill', function (d: any) {
        return d._children ? 'lightsteelblue' : '#fff';
      })
      .attr('cursor', 'pointer');

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

    // Transition exiting nodes to the parent's new position (and remove the nodes)
    var nodeExit = node.exit().transition()
      .duration(this.duration);

    nodeExit
      .attr('transform', function (d) {
        return 'translate(' + source.y + ',' + source.x + ')';
      })
      .remove();

    nodeExit.select('circle')
      .attr('r', 1e-6);

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

    // ****************** links section ***************************

    // Update the links…
    var link = this.svg.selectAll('path.link')
      .data(links, function (d: any) {
          return d.id;
        }
      );

    // Enter any new links at the parent's previous position.
    link.enter().insert('path', 'g')
      .attr('class', 'link')
      .attr('d', (d) => {
        var o = {x: source.x0, y: source.y0};
        return this.diagonal({source: o, target: o});
      });


    // Transition links to their new position.
    link.transition()
      .duration(this.duration)
      .attr('d', this.diagonal);


    // // Transition exiting nodes to the parent's new position.
    let linkExit = link.exit().transition()
      .duration(this.duration)
      .attr('d', (d: any) => {
        var o = {x: source.x, y: source.y};
        return this.diagonal({source: o, target: o});
      })
      .remove();

    // Stash the old positions for transition.
    nodes.forEach(function (d: any) {
      d.x0 = d.x;
      d.y0 = d.y;
    });

  }


}

Here is an exemple I did from this link : https://github.com/tomwanzek/d3-v4-definitelytyped/blob/master/tests/d3-hierarchy/d3-hierarchy-test.ts

 import { Component, Inject } from '@angular/core';
 import { Http } from '@angular/http';
 import {
     hierarchy,
     HierarchyNode,
     HierarchyPointNode,
     HierarchyLink,
     HierarchyPointLink,
     StratifyOperator,
     TreeLayout,
     tree,
     ClusterLayout,
     cluster
 } from 'd3-hierarchy'
 import * as d3 from 'd3';
 import { forEach } from '@angular/router/src/utils/collection';
 interface HierarchyDatum {
     name: string;
     value: number;
     children?: Array<HierarchyDatum>;
 }
 const data: HierarchyDatum = {
     name: "A1",
     value: 100,
     children: [
         {
             name: "B1",
             value: 100,
             children: [
                 {
                     name: "C1",
                     value: 100,
                     children: undefined 
                 },
                 {
                     name: "C2",
                     value: 300,
                     children: [
                         {
                             name: "D1",
                             value: 100,
                             children: undefined
                         },
                         {
                             name: "D2",
                             value: 300,
                             children: undefined
                         }
                     ] 
                 },
                 {
                     name: "C3",
                     value: 200,
                     children: undefined 
                 }
             ]
         },
         {
             name: "B2",
             value: 200,
             children: [
                 {
                     name: "C4",
                     value: 100,
                     children: undefined 
                 },
                 {
                     name: "C5",
                     value: 300,
                     children: undefined 
                 },
                 {
                     name: "C6",
                     value: 200,
                     children: [
                         {
                             name: "D3",
                             value: 100,
                             children: undefined
                         },
                         {
                             name: "D4",
                             value: 300,
                             children: undefined
                         }
                     ]  
                 }
             ]
         }
     ]
 };
 @Component({
     selector: 'chart',
     templateUrl: './chart.component.html',
     styleUrls: ['./chart.component.scss']
 })
 export class ChartComponent {
     private margin: any = { top: 20, right: 120, bottom: 20, left: 120 };
     private width: number;
     private height: number;
     private root: HierarchyPointNode<HierarchyDatum>;
     private tree: TreeLayout<HierarchyDatum>;
     private svg: any;
     private diagonal: any;
     constructor() {
     }
     ngOnInit() {
         this.width = 720 - this.margin.right - this.margin.left;
         this.height = 640 - this.margin.top - this.margin.bottom;
         this.svg = d3.select('.container').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("class", "g")
             //.attr("transform", "translate(5,5)");
             .attr("transform", "translate(" + this.margin.left + "," + this.margin.top + ")");
         d3.select('svg g.g')
             .append("g")
             .attr("class", "links");
         d3.select('svg g.g')
             .append("g")
             .attr("class", "nodes");
         console.log("flare inside", data);
         this.tree = tree<HierarchyDatum>();
         this.tree.size([this.height, this.width]);
         this.root = this.tree(hierarchy<HierarchyDatum>(data));
         this.draw(this.root);
     }
     private draw(root: HierarchyPointNode<HierarchyDatum>) {
         // Nodes
         d3.select('svg g.nodes')
             .selectAll('circle.node')
             .data(root.descendants())
             .enter()
             .append('circle')
             .classed('node', true)
             .attr('style', "fill: steelblue;stroke: #ccc;stroke-width: 3px;")
             .attr('cx', function (d) { return d.x; })
             .attr('cy', function (d) { return d.y; })
             .attr('r', 10);
         // Links
         d3.select('svg g.links')
             .selectAll('line.link')
             .data(root.links())
             .enter()
             .append('line')
             .classed('link', true)
             .attr('style', "stroke: #ccc;stroke-width: 3px;")
             .attr('x1', function (d) { return d.source.x; })
             .attr('y1', function (d) { return d.source.y; })
             .attr('x2', function (d) { return d.target.x; })
             .attr('y2', function (d) { return d.target.y; });
     }
 }

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