打字稿和d3版本v3中的可折叠树

时间:2017-11-13 02:24:43

标签: javascript angular typescript d3.js

我正在尝试使用d3(https://bl.ocks.org/mbostock/4339083)创建可折叠树 在Angular4项目中使用typescript。仅为最后一个节点显示的所有节点都没有生成我的树。 有人可以帮助如何在打字稿中创建d3可折叠树

有一些迭代或循环问题,我猜所有节点都没有迭代。

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

  }


}

1 个答案:

答案 0 :(得分:3)

以下是我在此链接中所做的示例: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; });
     }
 }