2017-10-19 61 views
0

我使用d3.tree創建我的樹層次結構,我對這個lib比較新,所以我需要一點幫助。當節點擴展時,d3 v4樹縮小

var treeData = {{ data | safe }}; 
      // Set the dimensions and margins of the diagram 
      var margin = {top: 30, right: 90, bottom: 30, left: 150}, 
       width = $('#tree-container').width(), 
       height = $('#tree-container').height(); 

      // append the svg object to the body of the page 
      // appends a 'group' element to 'svg' 
      // moves the 'group' element to the top left margin 
      var svg = d3.select("#tree-container").append("svg") 
       .attr("width", width) 
       .attr("height", height) 
       .call(d3.zoom().on("zoom", function() { 
        svg.attr("transform", d3.event.transform) 
       })) 
       .append("g") 
       .attr("width", width) 
       .attr("height", height) 
       .attr("id", "place") 
       .attr("transform", "translate(" 
         + (width/2) + "," + margin.top + ")"); 



      var i = 0, 
       duration = 750, 
       root; 

      // declares a tree layout and assigns the size 
      var treemap = d3.tree() 
       .nodeSize([70, 10]); 

      // Assigns parent, children, height, depth 
      root = d3.hierarchy(treeData, function(d) { return d.children; }); 

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

      // Collapse after the second level 
      root.children.forEach(collapse); 

      update(root); 

      // Collapse the node and all it's children 
      function collapse(d) { 
       if(d.children) { 
       d._children = d.children 
       d._children.forEach(collapse) 
       d.children = null 
       } 
      } 

      var nodes; 

      function update(source) { 

       // Assigns the x and y position for the nodes 
       var treeData = treemap(root); 

       // Compute the new tree layout. 
       nodes = treeData.descendants(); 
        links = treeData.descendants().slice(1); 

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

       // ****************** Nodes section *************************** 

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

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

       // Add Circle for the nodes 
       nodeEnter.append('circle') 
        .attr('class', 'node') 
        .attr('id', function(d) { return "circle-"+d.data.name; }) 
        .attr('r', 1e-6) 
        .style("fill", function(d) { 
         return d._children ? "lightsteelblue" : "#fff";// make text color appear read or as data.color 
        }).on('click', click); 

       // Add labels for the nodes 
       nodeEnter.append('text') 
        .attr("dy", "0.45em") 
        .attr("y", function(d) { 
         return d.children || d._children ? -13 : 13; 
        }) 
        .attr("text-anchor", function(d) { 
         return d.children || d._children ? "end" : "start"; 
        }) 
        .attr("cursor", "pointer") 
        .text(function(d) { return d.data.name; }) 
        .on("click", textClick); 

       // UPDATE 
       var nodeUpdate = nodeEnter.merge(node); 

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

       // Update the node attributes and style 
       nodeUpdate.select('circle.node') 
        .attr('r', 10) 
        .style("fill", function(d) { return d._children ? d.data.ncolor : "#fff"; }) // change color of inner circle 
        .style("stroke", function (d) { return d.data.ncolor; }) // changing color of outere circle 
        .attr('cursor', 'pointer'); 


       // Remove any exiting nodes 
       var nodeExit = node.exit().transition() 
        .duration(duration) 
        .attr("transform", function(d) { 
         return "translate(" + source.x + "," + source.y + ")"; 
        }) 
        .remove(); 

       // On exit reduce the node circles size to 0 
       nodeExit.select('circle') 
       .attr('r', 1e-6); 

       // On exit reduce the opacity of text labels 
       nodeExit.select('text') 
       .style('fill-opacity', 1e-6); 

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

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

       // Enter any new links at the parent's previous position. 
       var linkEnter = link.enter().insert('path', "g") 
        .attr("class", "link") 
        .style("stroke", function (d) { return d.data.color; }) // Place where color of previous link changes 
        .attr('d', function(d){ 
        var o = {x: source.x0, y: source.y0}; 
        return diagonal(o, o) 
        }); 

       // UPDATE 
       var linkUpdate = linkEnter.merge(link); 

       // Transition back to the parent element position 
       linkUpdate.transition() 
        .duration(duration) 
        .attr('d', function(d){ return diagonal(d, d.parent) }); 

       // Remove any exiting links 
       var linkExit = link.exit().transition() 
        .duration(duration) 
        .attr('d', function(d) { 
        var o = {x: source.x, y: source.y}; 
        return diagonal(o, o) 
        }) 
        .remove(); 

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



       // Creates a curved (diagonal) path from parent to the child nodes 
       function diagonal(s, d) { 

        path = "M" + s.x + "," + s.y + 
         "C" + (s.x + d.x)/2 + " " + s.y + "," 
          + (s.x + d.x)/2 + " " + d.y + "," 
          + d.x + " " + d.y; 


        return path 
       } 

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

它實際上有效,但我正在尋找的是讓我的視窗內有一切的方法。就像如果有人點擊節點,它會展開,如果子節點溢出(離開窗口),我需要縮小,以便它們可見。望有D3絕地高手回答我:)))

回答

0

這是很辛苦,沒有看到實際數據或代碼的運行版本回答,但這裏是一個建議。當你這樣做:

var treemap = d3.tree() 
    .nodeSize([70, 10]); 

你正在設置每個節點的大小,但不是整個佈局。另外,根據API

當指定節點大小時,根節點始終位於「0,0」處。

下面是一個例子:我只是分叉博斯托克的樹例如,設置nodeSize,你可以看到,節點會在SVG外:http://blockbuilder.org/anonymous/7a84944610c7e6b3b9ebf063977955c9

所以,一個可能的解決方案是使用size代替nodeSize

var treemap = d3.tree() 
    .nodeSize([width, height]); 

下面是使用size原樹例如,用於比較:http://blockbuilder.org/mbostock/4339083

+0

我實際上查看樹的文檔,並且我使用我的.nodeSize()出於某種原因,實際上,如果使用默認大小,則會有重疊的文本。 – ChynaJake

+0

順便提一下,這裏是樣本數據,你問。 「{」children「:[{」pid「:45757,」number_of_show「:2,」id「:48886,」level「:4,」belong_to「:」909555「,」name「:509060,」active「: true,「last_time_show」:「2017-10-20 11:30:06」}],「pid」:42167,「number_of_show」:2,「id」:45757,「level」:3,「belong_to」:「 909555「,」name「:308060,」active「:true,」last_time_show「:」2017-10-20 11:30:12「}' – ChynaJake

+0

在這種情況下(您的第一條評論),我建議您創建一個[MCVE ],否則將很難幫助你。 –