2014-11-12 7 views
5

में बच्चों की संख्या के अनुपात में मैं इस पर क्लिक करें विस्तार पतन नेटवर्क बनाया - http://jsfiddle.net/5Lv8gkqv/नोड आकार डी 3

var width = 960, 
    height = 500, 
    root = { 
"name": "Chocolate", "tag":"class", 
"children": [ 
    { 
    "name": "Wafer", "tag":"subclass", 
    "children": [ 
    { 
     "name": "Nestle", "tag":"company", 
    "children": [ 
     {"name": "KitKat", "tag":"product"} 
    ] 
    } 
    ] 
    }, 

    { 
    "name": "White", "tag":"subclass", 
    "children": [ 
    { 
     "name": "Nestle", "tag":"company", 
    "children": [ 
     {"name": "Milkybar", "tag":"product"} 
    ] 
    } 
    ] 
    }, 

    { 
    "name": "Caramel", "tag":"subclass", 
    "children": [ 
    { 
     "name": "Nestle", "tag":"company", 
    "children": [ 
     {"name": "BarOne", "tag":"product"} 
    ] 
    } 
    ] 
    },  
    { 
    "name": "Milk", "tag":"subclass", 
    "children": [ 
    { 
     "name": "Nestle", "tag":"company", 
    "children": [ 
     {"name": "Nestle Milk", "tag":"product"} 
    ] 
    }, { 
     "name": "Cadbury", "tag":"company", 
    "children": [ 
     {"name": "Dairy Milk", "tag":"product"} 
    ] 
    } 
    ] 
    } 




] 
}; 

var force = d3.layout.force() 
    .linkDistance(150) 
    .charge(-120) 
    .gravity(.05) 
    .size([width, height]) 
    .on("tick", tick); 

var svg = d3.select("body").append("svg") 
    .attr("width", width) 
    .attr("height", height); 

var link = svg.selectAll(".link"), 
    node = svg.selectAll(".node"); 

flatten(root); //to set ids 
setParents(root, null); 
collapseAll(root); 
root.children = root._children; 
root._children = null; 
update(); 

function update() { 
    var nodes = flatten(root), 
     links = d3.layout.tree().links(nodes); 
    // Restart the force layout. 
    force 
     .nodes(nodes) 
     .links(links) 
     .start(); 

    // Update links. 
    link = link.data(links, function(d) { return d.target.id; }); 

    link.exit().remove(); 

    link.enter().insert("line", ".node") 
     .attr("class", "link"); 

    // Update nodes. 
    node = node.data(nodes, function(d) { return d.id; }); 

    node.exit().remove(); 

    var nodeEnter = node.enter().append("g") 
     .attr("class", "node") 
     .on("click", click) 
     .call(force.drag); 

    nodeEnter.append("circle") 
     .attr("r", function(d) { return Math.sqrt(d.size)/10 || 4.5; }); 

    nodeEnter.append("text") 
     .attr("dy", ".35em") 
     .text(function(d) { return d.name; }); 

    node.select("circle") 
     .style("fill", color); 
} 

function tick() { 
    link.attr("x1", function(d) { return d.source.x; }) 
     .attr("y1", function(d) { return d.source.y; }) 
     .attr("x2", function(d) { return d.target.x; }) 
     .attr("y2", function(d) { return d.target.y; }); 

    node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); 
} 

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

// Toggle children on click. 
function click(d) { 
    if (d3.event.defaultPrevented) return; // ignore drag 
    if (d.children) { 
     collapseAll(d); 
    } else { 
     if (d._parent){ 
      d._parent.children.forEach(function(e){ 
       if (e != d){ 
        collapseAll(e); 
       } 
      }); 
     } 
    d.children = d._children; 
    d._children = null; 
    } 
    update(); 
} 

function collapseAll(d){ 
    if (d.children){ 
     d.children.forEach(collapseAll); 
     d._children = d.children; 
     d.children = null; 
    } 
    else if (d._childred){ 
     d._children.forEach(collapseAll); 
    } 
} 

// Returns a list of all nodes under the root. 
function flatten(root) { 
    var nodes = [], i = 0; 

    function recurse(node) { 
    if (node.children) node.children.forEach(recurse); 
    if (!node.id) node.id = ++i; 
    nodes.push(node); 
    } 
    recurse(root); 
    return nodes; 
} 

function setParents(d, p){ 
    d._parent = p; 
    if (d.children) { 
     d.children.forEach(function(e){ setParents(e,d);}); 
    } else if (d._children) { 
     d._children.forEach(function(e){ setParents(e,d);}); 
    } 
} 

बात अब अपनी यदि संभव हो तो नोड आकार संख्या के अनुपात के लिए है कि मैं सोच रहा था बच्चों का। तो माता-पिता नोड सबसे बड़ा सर्कल होगा और पत्ता नोड सबसे छोटा होगा, जबकि इंटरमीडिएट नोड-आकार प्रत्येक के बच्चों की संख्या पर निर्भर करेगा।

+1

यदि आप केवल तत्काल बच्चों की तलाश में हैं, तो आपको त्रिज्या सेट करते समय 'd.children.length' प्राप्त करने की आवश्यकता है: http://jsfiddle.net/5Lv8gkqv/1/ –

उत्तर

2

अपडेट किया गया: अब गिलशा के उत्तर से विचार का उपयोग करके दिखाए गए बच्चों को ध्यान में रखता है।

node.select("circle") 
    .attr("r", function(d){ 
     var numKids = 0; 
     if (d.children) numKids += d.children.length; 
     if (d._children) numKids += d._children.length; 
     return 10 * (numKids + 1); 
}) 

जहां r कुछ त्रिज्या है:


ज़रूर, आप प्रत्येक <circle> की त्रिज्या वे बच्चों की संख्या के अनुपात में निर्धारित कर सकते हैं। r=10 का उपयोग करना और "wafer" नोड पर टॉगल, तो आप इस मिल: enter image description here

+0

ठीक काम कर रहा है लेकिन Ive क्लिक करना है अपने आकार को बच्चों की संख्या के अनुपात में लाने के लिए "वेफर" पर। डिफ़ॉल्ट रूप से चॉकलेट सबसे बड़ा आता है, जबकि इसके 4 बच्चे एक ही आकार में आ रहे हैं। जो शूडेन्ट कोज "मिल्क" में दो बच्चे होते हैं और इस प्रकार "दूध" शड दूसरे सबसे बड़े नोड आकार में आ रहा है। आशा है कि आपको यह विचार मिलेगा – shalini

+0

@ शालिनी: अच्छा बिंदु, मेरा अद्यतन उत्तर देखें। – mdml

7

आप बच्चों की संख्या के अनुपात में नोड्स की त्रिज्या की गणना के लिए d3.scale.linear उपयोग कर सकते हैं। d3.scale एक सीमा के बीच में त्रिज्या खोजने में भी मदद करता है। यहाँ अद्यतन किया जाता है fiddle

var minRadius = 10; 
var maxRadius = 15; 
var scale = d3.scale.linear().range([minRadius,maxRadius]); 
nodeEnter.append("circle") 
    .attr("r", function(d) { 
     if(d.children) 
      return scale(d.children.length); 
     else if(d._children) 
      return scale(d._children.length); 
     else 
      return minRadius; 
    }); 
+0

आपके काम सही – shalini

2

एक पूर्ण समाधान के लिए, आप वास्तव में एक पुनरावर्ती समारोह का उपयोग करने के पहले कुल बच्चों (न केवल प्रथम स्तर बच्चों) प्रत्येक नोड की गणना करने के लिए चाहता हूँ। उदाहरण के लिए:

var bubble_up_total_children = function(node) { 
    var child, _i, _len, _ref; 
    if (node.children && node.children.length > 0) { 
    _ref = node.children; 
    for (_i = 0, _len = _ref.length; _i < _len; _i++) { 
     child = _ref[_i]; 
     bubble_up_total_children(child); 
    } 
    node.total_children = node.children.length + node.children.reduce(function(a, b) { 
     return a.total_children + b.total_children; 
    }); 
    } else { 
    node.total_children = 0; 
    } 
}; 

bubble_up_total_children(root); 

वहां से आप अब d3.scale उपयोग कर सकते हैं के रूप में पहले से ही में प्रलेखित @ Gilsha का जवाब प्रत्येक नोड पर नए total_children विशेषता के आधार पर आकार की गणना करने के लिए।

+1

अच्छी अंतर्दृष्टि – shalini

+1

रिकर्सिव एल्गोरिदम [सब कुछ हल करें] (https://www.youtube.com/watch?v=0zRjU038vl0)! –