2016-05-13 47 views
-1

因此,我已经构建了一个使用d3库将动画合拢/展开的树。我对d3仍然很陌生,我不确定如何将我的特定风格加入到战斗中。任何建议如何样式<g>标签?d3树<g>标记填充/边框整体造型

这是我希望它看起来像: enter image description here

而且这里是它目前的样子: enter image description here

下面是相关代码:

<!DOCTYPE html> 
<meta charset="utf-8"> 
<style> 
    .node { 
     cursor: pointer; 
    } 

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

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

    .link { 
     fill: none; 
     stroke: #ccc; 
     stroke-width: 2px; 
    } 
</style> 

<body> 
    <script src="//code.jquery.com/jquery-1.11.3.min.js"></script> 
    <script src="//d3js.org/d3.v3.min.js"></script> 
    <script> 
     var margin = { 
       top: 20, 
       right: 120, 
       bottom: 20, 
       left: 120 
      }, 
      width = $(window).width() - margin.right - margin.left, 
      height = $(window).height() - margin.top - margin.bottom; 

     var i = 0, 
      duration = 750, 
      root; 

     var tree = d3.layout.tree() 
      .size([height, width]) 

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

     buildJson(function (data) { 
      var svg = d3.select("body").append("svg") 
       .attr("width", width + margin.right + margin.left) 
       .attr("height", height + margin.top + margin.bottom) 
       .append("g") 
       .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

      root = data; 
      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); 

      d3.select(self.frameElement).style("height", "800px"); 

      function update(source) { 

       // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
       // Compute the new tree layout. 
       // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
       var nodes = tree.nodes(root).reverse(), 
        links = tree.links(nodes); 

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

       // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
       // Update the nodes… 
       // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
       var node = svg.selectAll("g.node") 
        .data(nodes, function(d) { 
         return d.id || (d.id = ++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", 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 ? -12 : 12; 
        }) 
        .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(duration) 
        .attr("transform", function(d) { 
         return "translate(" + d.y + "," + d.x + ")"; 
        }); 

       nodeUpdate.select("circle") 
        .attr("r", 4.5) 
        .style("fill", function(d) { 
         return d._children ? "lightsteelblue" : "#fff"; 
        }); 

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

       // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
       // Transition exiting nodes to the parent's new position. 
       // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
       var nodeExit = node.exit().transition() 
        .duration(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 = svg.selectAll("path.link") 
        .data(links, function(d) { 
         return d.target.id; 
        }); 

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

       // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
       // Transition links to their new position. 
       // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
       link.transition() 
        .duration(duration) 
        .attr("d", diagonal); 

       // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
       // Transition exiting nodes to the parent's new position. 
       // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
       link.exit().transition() 
        .duration(duration) 
        .attr("d", function(d) { 
         var o = { 
          x: source.x, 
          y: source.y 
         }; 
         return diagonal({ 
          source: o, 
          target: o 
         }); 
        }) 
        .remove(); 

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

       // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
       // Remove Root Node, ultra mega important!!! 
       // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
       node.each(function(d){ 
        if (d.name == "flare") 
         d3.select(this).remove();}); 
       link.each(function(d){ 
        if (d.source.name == "flare") 
         d3.select(this).remove();}); 
      } 

      // Toggle children on click. 
      function click(d) { 
       if (d.children) { 
        d._children = d.children; 
        d.children = null; 
       } 
       else { 
        d.children = d._children; 
        d._children = null; 
       } 
       // If the node has a parent, then collapse its child nodes 
       // except for this clicked node. 
       if (d.parent) { 
        d.parent.children.forEach(function(element) { 
         if (d !== element) { 
          collapse(element); 
         } 
        }); 
       } 
       update(d); 
      } 

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

     }); 

     // Get Data and format it properly for presentation 
     function getJsonData (pathToData, callback) { 
      $.getJSON(pathToData, function() { 
       console.log("Retrieving: " + pathToData); 
      }).done(function(data) { 
       callback({ 
        error: false, 
        data: data 
       }); 
      }) 
      .fail(function() { 
       callback({ 
        error: true 
       }); 
      }); 
     } 

     function buildJson (builder) { 
      var runOnce = true, categories_raw, technologies_raw, formatted_json = { 
       'name' : 'flare', 
       'children' : [] 
      } 

      //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
      // First get all of the categories and subcategories 
      //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
      getJsonData('assets/json/categories.json', function (data) { 
       if (!data.error) { 
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
        // Categories and Subcategories Retreived now build it out 
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
        categories_raw = data.data 

        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
        // Technologies retreived now build it out 
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
        getJsonData('assets/json/technologies.json', function (data) { 
         if (!data.error) { 
          technologies_raw = data.data 

          var categories = categories_raw[0], subcategories = categories_raw[1], technologies = technologies_raw, formatted_categories = [], formatted_subcategories = [], formatted_technologies = [] 

          subcategories.forEach (function (value, index) { 
           formatted_subcategories.push({ 
            'name' : value.label, 
            'id' : value.id, 
            'children' : [], 
            'parent' : value.parent 
           }) 
          }) 

          technologies.forEach (function (value, index) { 
           var result = formatted_subcategories.filter(function(obj) { 
            return obj.id == value.subCat; 
           }); 

           if (typeof result[0] != 'undefined') { 
            result[0].children.push({ 
             'name' : value.label 
            }) 
           } 
          }) 

          categories.forEach (function (value, index) { 
           var result = formatted_subcategories.filter(function(obj) { 
            return obj.parent == value.id; 
           }); 

           formatted_json.children.push({ 
            'name' : value.label, 
            'id' : value.id, 
            'children' : result 
           }) 
          }) 

          builder(formatted_json) 
         } 
        }) 
       } 
      }) 
     } 
    </script> 
+0

你的数据是什么样的?所以我可以创建一个小提琴.. – thatOneGuy

+0

这里是一些可以工作的json的要点https://gist.github.com/Quixomatic/4cc96a44bca4fb81ce963ceaada89569 –

+0

您正在使用两组数据:类别,json和technologies.json .. – thatOneGuy

回答