2016-10-15 14 views
2

私はd3が初めてで、v4のhttps://bl.ocks.org/mbostock/4063550 の折りたたみバージョンを作成しようとしています。 v3でも同じことを説明するさまざまな例がありますが、v4では適切なものを見つけることができませんでした。 子供たちが開いているonClick関数を実装しましたが、リンクがクリック後に間違って配置されるという問題があります。それらは右にシフトし、ノードは同じ位置にとどまる。 更新機能のための私のコードの下に見つけてください:d3 v4の折りたたみ可能な放射状ツリー

<!DOCTYPE html> 
<meta charset="utf-8"> 
<style> 
<!-- 
.node circle { 
    //fill: #999; 
    fill: #fff; 
    stroke: steelblue; 
    stroke-width: 3px; 
} 



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

.node--internal circle { 
    fill: #555; 
} 

.node--internal text { 
    text-shadow: 0 1px 0 #fff, 0 -1px 0 #fff, 1px 0 0 #fff, -1px 0 0 #fff; 
} 

.link { 
    fill: none; 
    stroke: #555; 
    stroke-opacity: 0.4; 
    stroke-width: 1.5px; 
} 
--> 
.node { 
    cursor: pointer; 
} 

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

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

.link { 
    fill: none; 
    stroke: #ccc; 
    stroke-width: 1.5px; 
</style> 
<body> 
<script src="//d3js.org/d3.v4.min.js"></script> 
<script> 



var width = 960, 
height = 1000, 
duration = 750; 

var nodes,links; 
    var i = 0; 


    var svg = d3.select("body").append("svg") 
       .attr("width",width) 
       .attr("height",height); 
    var g = svg.append("g").attr("transform", "translate(" + (width/2 + 40) + "," + (height/2 + 90) + ")"); 

    function connector(d) { 
     return "M" + project(d.x, d.y) 
            + "C" + project(d.x, (d.y + d.parent.y)/2) 
            + " " + project(d.parent.x, (d.y + d.parent.y)/2) 
            + " " + project(d.parent.x, d.parent.y) 
    /* 
    return "M" + d.y + "," + d.x + 
    "C" + (d.y + d.parent.y)/2 + "," + d.x + 
    " " + (d.y + d.parent.y)/2 + "," + d.parent.x + 
    " " + d.parent.y + "," + d.parent.x; */ 
} 



    var treeMap = d3.tree() 
    .size([360,250]), 
    root; 
    var nodeSvg, linkSvg, nodeEnter, linkEnter ; 



    d3.json("treeData.json",function(error,treeData){ 
     if(error) throw error; 

     root = d3.hierarchy(treeData,function(d){ 
      return d.children; 
     }); 

     root.each(function (d) { 
     console.log(d); 
       d.name = d.data.name; //transferring name to a name variable 
       d.id = i; //Assigning numerical Ids 
       i += i; 
      }); 

     root.x0 = height/2; 
      root.y0 = 0; 

      function collapse(d) { 
    if (d.children) { 
     d._children = d.children; 
     d._children.forEach(collapse); 
     d.children = null; 
    } 
    } 
     //root.children.forEach(collapse); 
      update(root); 
    }); 


function update(source) { 


     //root = treeMap(root); 
     nodes = treeMap(root).descendants(); 
     //console.log(nodes); 
     //links = root.descendants().slice(1); 
     links = nodes.slice(1); 
     //console.log(links); 
     var nodeUpdate; 
       var nodeExit; 

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

    nodeSvg = g.selectAll(".node") 
        .data(nodes,function(d) { return d.id || (d.id = ++i); }); 


     //nodeSvg.exit().remove(); 

     var nodeEnter = nodeSvg.enter() 
        .append("g") 
        //.attr("class", function(d) { return "node" + (d.children ? " node--internal" : " node--leaf"); }) 
        .attr("class", "node") 
        .attr("transform", function(d) { return "translate(" + project(d.x, d.y) + ")"; }) 
        //.attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; }) 
        .on("click",click) 
        .on("mouseover", function(d) { return "minu"; }); 



     nodeEnter.append("circle") 
      .attr("r", 5) 
      .style("fill", color); 



     nodeEnter.append("text") 
      .attr("dy", ".31em") 
      //.attr("x", function(d) { return d.x < 180 === !d.children ? 6 : -6; }) 
      .attr("x", function(d) { return d.children || d._children ? -10 : 10; }) 
      .style("text-anchor", function(d) { return d.x < 180 === !d.children ? "start" : "end"; }) 
      //.attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; }) 
      .attr("transform", function(d) { return "rotate(" + (d.x < 180 ? d.x - 90 : d.x + 90) + ")"; }) 
      .text(function(d) { return d.data.name; }); 

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


    nodeSvg.select("circle") 
     .style("fill", color); 


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

     // Transition exiting nodes to the parent's new position. 
    var nodeExit = nodeSvg.exit().transition() 
     .duration(duration) 
     .attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; }) //for the animation to either go off there itself or come to centre 
     .remove(); 

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

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

     nodes.forEach(function(d) { 
    d.x0 = d.x; 
    d.y0 = d.y; 
    }); 


     linkSvg = g.selectAll(".link") 
        .data(links, function(link) { var id = link.id + '->' + link.parent.id; return id; }); 



     // Transition links to their new position. 
       linkSvg.transition() 
        .duration(duration); 
        // .attr('d', connector); 

     // Enter any new links at the parent's previous position. 
       linkEnter = linkSvg.enter().insert('path', 'g') 
        .attr("class", "link") 
        .attr("d", function(d) { 
           return "M" + project(d.x, d.y) 
            + "C" + project(d.x, (d.y + d.parent.y)/2) 
            + " " + project(d.parent.x, (d.y + d.parent.y)/2) 
            + " " + project(d.parent.x, d.parent.y); 
          }); 
          /* 
          function (d) { 
         var o = {x: source.x0, y: source.y0, parent: {x: source.x0, y: source.y0}}; 
         return connector(o); 
        });*/ 



        // Transition links to their new position. 
       linkSvg.merge(linkEnter).transition() 
        .duration(duration) 
        .attr("d", connector); 


        // Transition exiting nodes to the parent's new position. 
       linkSvg.exit().transition() 
        .duration(duration) 
        .attr("d", /*function (d) { 
         var o = {x: source.x, y: source.y, parent: {x: source.x, y: source.y}}; 
         return connector(o); 
        })*/function(d) { 
           return "M" + project(d.x, d.y) 
            + "C" + project(d.x, (d.y + d.parent.y)/2) 
            + " " + project(d.parent.x, (d.y + d.parent.y)/2) 
            + " " + project(d.parent.x, d.parent.y); 
          }) 
        .remove(); 

        // Stash the old positions for transition. 


} 

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


function color(d) { 
    return d._children ? "#3182bd" // collapsed package 
     : d.children ? "#c6dbef" // expanded package 
     : "#fd8d3c"; // leaf node 
} 


function flatten (root) { 
    // hierarchical data to flat data for force layout 
    var nodes = []; 
    function recurse(node) { 
    if (node.children) node.children.forEach(recurse); 
    if (!node.id) node.id = ++i; 
    else ++i; 
    nodes.push(node); 
    } 
    recurse(root); 
    return nodes; 
} 


function project(x, y) { 
    var angle = (x - 90)/180 * Math.PI, radius = y; 
    return [radius * Math.cos(angle), radius * Math.sin(angle)]; 
} 

</script> 
</body> 
</html> 

treeData.json:

{ 
    "name": "United States", 
    "children": [ 
    { 
     "name": "Arizona", 
     "children":[ 
     { "name" : "Arizona Airport", "size": 13} 
     ] 
    }, 
    { 
     "name": "California", 
     "children":[ 
     {"name": "San Francisco","size":15}, 
     {"name": "San Jose","size":25}, 
     {"name": "Los Angeles","size":17} 
     ] 
    }, 
    { 
     "name": "Illinois", 
     "children":[ 
     { "name" : "Chicago O'Hare", "size": 13}, 
     { "name" : "Midway", "size": 18 } 
     ] 
    }, 
    { 
     "name": "Colorado", 
     "children" : [ 
     { "name": "Denver","size": 7} 
     ] 
    }, 
    { 
     "name": "Florida","size":2 
    }, 
    { 
     "name": "Georgia", "size": 25 
    }, 
    { 
     "name": "Kentucky","size":2 
    }, 
    { 
     "name": "Massachussets", "size": 25 
    }, 
    { 
     "name": "Michigan","size":2 
    }, 
    { 
     "name": "Minnesota", "size": 25 
    }, 
    { 
     "name": "Missouri","size":2 
    }, 
    { 
     "name": "North Carolina", "size": 25 
    }, 
    { 
     "name": "Nevada","size":2 
    }, 
    { 
     "name": "Newyork", "size": 12 
    }, 
    { 
     "name": "Oregon","size":2 
    }, 
    { 
     "name": "Pennsylvania", "size": 25 
    }, 
    { 
     "name": "Washington", 
     "children": [ 
     { "name" : "Seattle","size" : 13} 
     ] 
    }, 
    { 
     "name": "Hawaii", "size": 25 
    }, 
    { 
     "name": "Texas", 
     "children" : [ 
     { "name": "Dallas" ,"size": 9}, 
     { "name": "Houston" ,"size": 13}, 
     { "name": "Austin" ,"size": 17} 
     ] 
    }, 
    { 
     "name": "Utah", "size": 25 
    }, 
    { 
     "name": "Virginia", "size": 25 
    } 
    ] 
} 
+0

ノードの移動を**アップデート選択**で処理していません。リンクが新しい位置に移動しているように見えますが、ノードはそうではありません。 ** working **サンプルのコードを作成できれば、私はあなたのためにそれをきれいにすることができますが、私は自分自身でそれを試して再現するのは面倒です。 – Mark

+0

私はコードを更新しました。回答いただきありがとうございます。 – Minu

+1

Hey Mark!提案していただきありがとうございます。それは完璧に働いています! – Minu

答えて

3

@Minuは、問題のコードを更新するので、ここで私はそれを得るためにやったことだしませんでした作品:

だけ変更します。これに

// Transition nodes to their new position. 
var nodeUpdate = nodeSvg.merge(nodeEnter).transition() 
.duration(duration); 

を:

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

これは、放射状のツリーを折りたたみ可能にしたいと思っている他の人にとって有益です。

関連する問題