Javascript 角度2 D3树未正确渲染

Javascript 角度2 D3树未正确渲染,javascript,angular,typescript,d3.js,tree,Javascript,Angular,Typescript,D3.js,Tree,我有一个用d3(v3)在纯javascript中生成的树,我正试图将其转换为Angular2组件。但是,我很难让它正确显示 下面是我在tree.component.ts中的代码内容: import { Component, OnInit, OnChanges, ViewChild, ElementRef, Input, ViewEncapsulation } from '@angular/core'; import * as d3 from 'd3'; @Component({ sele

我有一个用d3(v3)在纯javascript中生成的树,我正试图将其转换为Angular2组件。但是,我很难让它正确显示

下面是我在tree.component.ts中的代码内容:

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


@Component({
  selector: 'app-tree',
  templateUrl: './tree.component.html',
  styleUrls: ['./tree.component.css']
})
export class TreeComponent {
@ViewChild('tree') private chartContainer: ElementRef;
@Input() private data: Array<any>;

private dataInfo2 = {
  "name": "rootAlert",
  "alert": "true",
  "children": [{
    "name": "Child1",
    "alert": "true",
    "children": [{
      "name": "Child1-1",
      "alert": "false"
    }, {
      "name": "Child1-2",
      "alert": "false"
    }, {
      "name": "Child1-3",
      "alert": "true"
    }]
  }, {
    "name": "Child2",
    "alert": "false",
    "children": [{
      "name": "Child2-1",
      "alert": "false"
    }, {
      "name": "Child2-2",
      "alert": "false"
    }, {
      "name": "Child2-3",
      "alert": "false"
    }]
  }, {
    "name": "Child3",
    "alert": "false"
  }]
}

private values = this.dataInfo2
//console.log(JSON.stringify(values))

//private element = this.chartContainer.nativeElement;;
private div = d3.select("body")
        .append("div") // declare the tooltip div
        .attr("class", "tooltip")
        .style("opacity", 0);
private switcher = true;
private margin = { top: 20, right: 120, bottom: 20, left: 120 };
private width = 960 - this.margin.right - this.margin.left;
private height = 800 - this.margin.top - this.margin.bottom;
private i = 0;
private duration = 750;
private root;
private select2_data;
private diameter = 960;
private tree = d3.layout.tree()
    .size([this.height, this.width]);

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

private svg = d3.select("body").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 + ")");


ngOnInit(){

  this.root = this.values;
  //values is the flare.json
  //select2_data = extract_select2_data(values, [], 0)[1];//I know, not the prettiest...
  this.root.x0 = this.height / 2;
  this.root.y0 = 0;
  this.root.children.forEach((item)=>this.collapse(item));
  this.update(this.root);
  d3.select(self.frameElement).style("height", "800px");

}



setAllFalse(root){
  if (!root.childAlerts){
    root.severity = false
    root.class = 'nf'
    console.log("set " + root.sourceName + "to false")
    return
  }
  else{
    for (var i = 0; i < root.childAlerts.length; i++){
        this.setAllFalse(root.childAlerts[i])

    }
  }
  root.severity = false
  root.class = 'nf'
  return
}

//recursively collapse children
collapse(d: any) {

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

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

openPaths(paths) {
    for (var i = 0; i < paths.length; i++) {
        if (paths[i].id !== "1") {//i.e. not root
            paths[i].class = 'found';
            if (paths[i]._children) { //if children are hidden: open them, otherwise: don't do anything
                paths[i].children = paths[i]._children;
                paths[i]._children = null;
            }
            this.update(paths[i]);
        }
    }
}

openPaths2(paths) {
    for (var i = 0; i < paths.length; i++) {
        if (paths[i].id !== "1") {//i.e. not root
            paths[i].class = 'nf';
            if (paths[i]._children) { //if children are hidden: open them, otherwise: don't do anything
                paths[i].children = paths[i]._children;
                paths[i]._children = null;
            }
            this.update(paths[i]);
        }
    }
}



update(source) {
    // Compute the new tree layout.


    var nodes = this.tree.nodes(this.root).reverse(),
    links = this.tree.links(nodes);

    // Normalize for fixed-depth.
    nodes.forEach(function (d) { d.y = d.depth * 180; });

    // Update the nodes…
    var 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 (d) { return "translate(" + source.y0 + "," + source.x0 + ")"; })
    .on("click", this.click);

    nodeEnter.append("circle")
    .attr("r", 1e-6)
    .style("fill", function (d) { return d._children ? "lightsteelblue" : "#fff"; });

    nodeEnter.append("text")
        .attr("x", function (d) { return d.children || d._children ? -10 : 10; })
        .attr("dy", ".35em")
        .attr("text-anchor", function (d) { return d.children || d._children ? "end" : "start"; })
        .text(function (d) { return d.name; })
        .style("fill-opacity", 1e-6);

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

    nodeUpdate.select("circle")
        .attr("r", 4.5)
        .style("fill", function (d) {
            if (d.class === "found") {
                return "#ff4136"; //red
            }
            else if (d._children) {
                return "lightsteelblue";
            }
            else {
                return "#fff";
            }
        })
        .style("stroke", function (d) {
            if (d.class === "found") {
                return "#ff4136"; //red
            }
        });

    nodeUpdate.select("text") //NOCARRY
        .style("fill-opacity", 1);

    // Transition exiting nodes to the parent's new position.
    var nodeExit = node.exit().transition()
        .duration(this.duration)
        .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);

    // Update the links…
    var link = this.svg.selectAll("path.link")
        .data(links, function (d: any) { return d.target.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)
        .style("stroke", function (d) {
          console.log("d IS")
          console.log(d)
          console.log("AND ITS TARGET IS")
          console.log(d.target)
            if (d.target.class === "found") {
                return "#ff4136";
            }
        });

    // Transition exiting nodes to the parent's new position.
    link.exit().transition()
        .duration(this.duration)
        .attr("d", function (d) {
            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;
    });
}

searchTree(obj, search, path) {
  console.log("ROOT IS ")
  console.log(obj)
    if (obj.name === search) { //if search is found return, add the object to the path and return it
        path.push(obj);
        return path;
    }
    else if (obj.children || obj._children) { //if children are collapsed d3 object will have them instantiated as _children
        var children = (obj.children) ? obj.children : obj._children;
        for (var i = 0; i < children.length; i++) {
            path.push(obj);// we assume this path is the right one
            var found = this.searchTree(children[i], search, path);
            if (found) {// we were right, this should return the bubbled-up path from the first if statement
                return found;
            }
            else {//we were wrong, remove this parent from the path and continue iterating
                path.pop();
            }
        }
    }
    else {//not the right object, return false so it will continue to iterate in the loop
        return false;
    }
}
}
我唯一将普通js更改为这个的是使所有变量成为TreeComponent类的一部分,并使类方法相应地作用于它们。我曾尝试将原始svg锚定到其他元素,但这根本不会呈现,因此这里将svg装载到body元素上。这是我看到的一个例子

我希望它像这样:(它将如何在纯js中呈现) 有人知道这里发生了什么吗?在我看来,只有一个节点和路径被附加,然后它就停止了

您可以设置css

.link {
    fill: none;
    stroke: #ccc;
    stroke-width: 2px;
}
您可以设置css

.link {
    fill: none;
    stroke: #ccc;
    stroke-width: 2px;
}

好吧,我已经知道我的问题是什么了

d3将自己的元素附加到DOM中,angular 2不知道这一点,所以当我以angular方式添加css元素时,它们被忽略,因为angular看不到d3添加的元素。因此,我必须添加以下内容,以便我的css可以应用,甚至可以应用于d3中动态生成的元素:

@Component({
  selector: 'tree',
  template:`
          <div></div>
          `,
  styleUrls: ['./tree.component.css'],
  encapsulation: ViewEncapsulation.None  //No view encapsulation for D3 components
})
@组件({
选择器:'树',
模板:`
`,
样式URL:['./tree.component.css'],
封装:视图封装。无//D3组件无视图封装
})
添加此项后,组件css将应用自身


我遇到的另一个问题其实很简单。我对
这个
在组件方法中所指的内容做出了错误的假设。这就是为什么只绘制一个节点和一个链接的根本原因。

好吧,我已经找出了我的问题所在

d3将自己的元素附加到DOM中,angular 2不知道这一点,所以当我以angular方式添加css元素时,它们被忽略,因为angular看不到d3添加的元素。因此,我必须添加以下内容,以便我的css可以应用,甚至可以应用于d3中动态生成的元素:

@Component({
  selector: 'tree',
  template:`
          <div></div>
          `,
  styleUrls: ['./tree.component.css'],
  encapsulation: ViewEncapsulation.None  //No view encapsulation for D3 components
})
@组件({
选择器:'树',
模板:`
`,
样式URL:['./tree.component.css'],
封装:视图封装。无//D3组件无视图封装
})
添加此项后,组件css将应用自身


我遇到的另一个问题其实很简单。我对
这个
在组件方法中所指的内容做出了错误的假设。这就是为什么只绘制一个节点和一个链接的根本原因。

首先,为什么不使用d3版本4?那么,你能准确地解释一下你想做什么,以及你想要什么结果吗?@pirs使用版本4需要重写大量的代码。我们有许多利基功能,我们并不热衷于重新启动v4带来的变化。我上传了一张图片,展示了可视化基本上应该是什么样子。这显然是理解如何掌握代码的最佳方式,互联网上有很多这样的例子:请放一个干净的代码,并有足够的解释,这样它也可以对其他人有用。代码中有很多未使用的变量和函数。首先,为什么不使用d3版本4?那么,你能准确地解释一下你想做什么,以及你想要什么结果吗?@pirs使用版本4需要重写大量的代码。我们有许多利基功能,我们并不热衷于重新启动v4带来的变化。我上传了一张图片,展示了可视化基本上应该是什么样子。这显然是理解如何掌握代码的最佳方式,互联网上有很多这样的例子:请放一个干净的代码,并有足够的解释,这样它也可以对其他人有用。你的代码中有很多未使用的变量和函数是的,我的css文件中已经有了这些变量和函数,我在上面对它们进行了编辑现在我看到了,tree.component.css中的css不起作用,但是如果我在index.html中添加样式标签,它至少修复了奇怪的黑色填充效果,我更新了上面的图片是的,实际上,我的css文件中已经有了它,我在上面编辑过,现在我看到了,tree.component.css中的css不起作用,但是如果我在index.html中添加样式标记,它至少修复了奇怪的黑色填充效果,我更新了上面的图片我正在尝试上面的代码并得到错误类型错误:无法读取未定义的属性“tree”,可以告诉我如何修复它吗?请发布您为使此代码正常工作所做的修改?我正在尝试上面的代码并得到错误类型错误:无法读取未定义的属性“tree”,你能告诉我如何修复它吗?你能发布你为使代码正常工作所做的修改吗?