2017-10-20 14 views
1

私はAngular2コンポーネントに移行しようとしているプレーンなjavascriptでd3(v3)で作成されたツリーを持っています。しかし、正しく表示するのが難しいです。角2のD3ツリーが正しくレンダリングされない

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

そして、ここでは

.node { 
    cursor: pointer; 
} 

.node circle { 
    fill: #fff; 
    stroke: steelblue; 
    stroke-width: 1.5px; 
} 

.found { 
    fill: #ff4136; 
    stroke: #ff4136; 
} 

.node text { 
    font: 10px sans-serif; 
} 

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

tree.component.css私は無地のjsから変更しただけのものですこれには、すべての変数をTreeComponentクラスの一部にし、それに応じてクラスメソッドを動作させることです。私は元のsvgを他の要素に固定しようとしましたが、決してレンダリングしないので、ここではsvgをbody要素にマウントします。ここに私が見ているものの例があります。

enter image description here

私はそれがこれを似せて探しています:(それはプレーンなJSでレンダリングだろうか) enter image description here 誰もがここで何が起こっているかに任意の洞察力を持っていますか? 1つのノードとパスだけが追加されるように見えます。

+0

まず、なぜd3バージョン4を使用しないのですか?それでは、あなたは何をしようとしているのか、どんな結果を望んでいるのか正確に説明できますか? – pirs

+0

@pirsバージョン4を使用するには、これを超えるかなりの量のコードを書き直す必要があります。私たちは、v4がもたらす変化を再開したくないニッチな機能をいくつか持っています。私は、視覚化が基本的にどのように見えているのかのイメージをアップロードしました。 – jzeef

+0

これは明らかにあなたのコードをマスターする方法を理解するための最良の方法です。インターネット上にたくさんの例があります。https://bl.ocks.org/d3noob/43a860bc0024792f8803bba8ca0d5ecd – pirs

答えて

0

よしを設定することができますので、私は私の問題は何であったか考え出しました。

d3はそれ自身の要素をDOMに追加し、角度2はこれを知らないので、CSS要素を角型で追加すると、D3が追加した要素が角度に表示されないため無視されます。だから私はD3から、私のCSSは適用されるようにしても、動的に生成するための要素を以下を追加する必要がありました:

@Component({ 
    selector: 'tree', 
    template:` 
      <div></div> 
      `, 
    styleUrls: ['./tree.component.css'], 
    encapsulation: ViewEncapsulation.None //No view encapsulation for D3 components 
}) 

これを追加した後、コンポーネントのCSSは自身を適用します。

今、私が持っていたもう一つの問題は、実際にはかなり簡単でした。私はコンポーネントメソッドでthisが何を参照しているかについて誤った仮定をしていました。これは、なぜ1つのノードと1つのリンクだけが描画されたのかの根源です。

0

あなたはCSS

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

はい、私は実際には既に私のCSS私が上で編集したファイル – jzeef

+0

tree.component.cssのCSSは動作していませんが、index.htmlのスタイルタグを付け加えれば、少なくとも奇妙な黒の塗りつぶし効果が修正されます、私は上記の画像を更新しました – jzeef

関連する問題